Index: leahi.qrc =================================================================== diff -u -r0dfba44fb7172b9458d161b3ed5f54527f93b698 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- leahi.qrc (.../leahi.qrc) (revision 0dfba44fb7172b9458d161b3ed5f54527f93b698) +++ leahi.qrc (.../leahi.qrc) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -110,6 +110,8 @@ resources/images/eye_closed.png resources/images/stepCheck.png resources/images/complete_check.png + resources/images/water_sample_fail.png + resources/images/water_sample_pass.png sources/gui/qml/components/MainMenu.qml @@ -175,6 +177,7 @@ sources/gui/qml/components/IdleTimer.qml sources/gui/qml/components/TreatmentCompleteButton.qml sources/gui/qml/components/RangedValue.qml + sources/gui/qml/components/SubStepIndicator.qml sources/gui/qml/compounds/PressureRangeSlider.qml @@ -247,18 +250,17 @@ sources/gui/qml/pages/pretreatment/PreTreatmentBase.qml sources/gui/qml/pages/pretreatment/PreTreatmentStack.qml - sources/gui/qml/pages/pretreatment/PreTreatmentWaterSampleStack.qml - sources/gui/qml/pages/pretreatment/PreTreatmentConsumablesStack.qml - sources/gui/qml/pages/pretreatment/PreTreatmentPrimeStack.qml + sources/gui/qml/pages/pretreatment/PreTreatmentWaterSample.qml + sources/gui/qml/pages/pretreatment/PreTreatmentSelfTests.qml + sources/gui/qml/pages/pretreatment/PreTreatmentPrime.qml + sources/gui/qml/pages/pretreatment/PreTreatmentInstallStack.qml + sources/gui/qml/pages/pretreatment/PreTreatmentUltrafiltration.qml sources/gui/qml/pages/pretreatment/create/PreTreatmentCreate.qml sources/gui/qml/pages/pretreatment/create/PreTreatmentCreateContent.qml - - sources/gui/qml/pages/pretreatment/connection/PreTreatmentUltrafiltration.qml - sources/gui/qml/pages/pretreatment/connection/PreTreatmentConnectionStack.qml - + sources/gui/qml/pages/treatment/TreatmentStack.qml sources/gui/qml/pages/treatment/TreatmentHome.qml Index: sources/gui/GuiGlobals.h =================================================================== diff -u -r0dfba44fb7172b9458d161b3ed5f54527f93b698 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/GuiGlobals.h (.../GuiGlobals.h) (revision 0dfba44fb7172b9458d161b3ed5f54527f93b698) +++ sources/gui/GuiGlobals.h (.../GuiGlobals.h) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -190,9 +190,9 @@ ID_AdjustPatientConnectionConfirmReq = 0x660F, // 102 //// ----- @CRAPIZED: had to change to avoid duplication ID_AdjustPatientConnectionConfirmRsp = 0x670F, // 103 //// ----- @CRAPIZED: had to change to avoid duplication // Pre-Treatment Start Treatment - ID_AdjustStartTreatmentReq = 0x7100, // 113 - ID_AdjustStartTreatmentRsp = 0x720F, // 114 //// ----- @CRAPIZED: had to change to avoid duplication - + ID_AdjustStartTreatmentReq = 0x9000, // 113 + ID_AdjustStartTreatmentRsp = 0x9100, // 114 + // DG Data Messages ID_DGROPumpData = 0x1F0F, // 31 //// ----- @CRAPIZED: had to change to avoid duplication ID_DGDrainPumpData = 0x240F, // ?? //// ----- @CRAPIZED: had to change to avoid duplication Index: sources/gui/qml/components/ConfirmButton.qml =================================================================== diff -u -r8e9ab09c145174b7912fc13f0ea906572a45ad9c -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/components/ConfirmButton.qml (.../ConfirmButton.qml) (revision 8e9ab09c145174b7912fc13f0ea906572a45ad9c) +++ sources/gui/qml/components/ConfirmButton.qml (.../ConfirmButton.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -21,7 +21,7 @@ TouchRect { id : _root width : Variables.confirmButtonWidth - height : 50 + height : Variables.contentHeight text { text: qsTr("Confirm") font.pixelSize: Fonts.fontPixelConfirm Index: sources/gui/qml/components/HeaderBar.qml =================================================================== diff -u -r0dfba44fb7172b9458d161b3ed5f54527f93b698 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/components/HeaderBar.qml (.../HeaderBar.qml) (revision 0dfba44fb7172b9458d161b3ed5f54527f93b698) +++ sources/gui/qml/components/HeaderBar.qml (.../HeaderBar.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -11,6 +11,7 @@ property alias loggedUser : _loggedInUser.text readonly property int currentScreen : _headerMenu.currentScreen property alias statusColor : _headerMenu.statusColor + property bool isCreateRx : false // set in slot in parent width : Variables.applicationWidth height : Variables.headerHeight @@ -145,8 +146,7 @@ extraSpace : _headerButtonRow.spacing visible : vTDOpMode.preTreatment || vTDOpMode.inTreatment || - vTDOpMode.postTreatment || - vTDOpMode.validateParameters + vTDOpMode.postTreatment onPressed : _treatmentAdjustmentVitals.open() } @@ -155,9 +155,9 @@ iconSize : Variables.headerIconDiameter iconImageSource : "qrc:/images/iPrescription" extraSpace : _headerButtonRow.spacing - visible : vTDOpMode.preTreatment || - vTDOpMode.inTreatment || - vTDOpMode.postTreatment + visible :( vTDOpMode.preTreatment || + vTDOpMode.inTreatment || + vTDOpMode.postTreatment ) && ! _root.isCreateRx onPressed : _headerbarPrescription.open() } Index: sources/gui/qml/components/StackItem.qml =================================================================== diff -u -r3ef1a4ff361ba1774ad1a6f6170dbb174cadbdd5 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/components/StackItem.qml (.../StackItem.qml) (revision 3ef1a4ff361ba1774ad1a6f6170dbb174cadbdd5) +++ sources/gui/qml/components/StackItem.qml (.../StackItem.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -119,5 +119,6 @@ StackView { id : _stackView initialItem : null anchors.fill: parent + StackView.onActivated: print("onActivated") } } Index: sources/gui/qml/components/StepBullet.qml =================================================================== diff -u -rb59827b661a423b2b1ad2ca7b8611c2c0be7bd6a -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/components/StepBullet.qml (.../StepBullet.qml) (revision b59827b661a423b2b1ad2ca7b8611c2c0be7bd6a) +++ sources/gui/qml/components/StepBullet.qml (.../StepBullet.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -38,7 +38,8 @@ property color colorInComplete : Colors.borderDisableButton property int fontSizeCurrent : Fonts.fontPixelStepCurrent property int fontSizeNormal : Fonts.fontPixelStepNormal - property real diameter : 15 + property real diameter : 15 + property bool showCompleteCheck: true QtObject { id: _private @@ -68,7 +69,7 @@ anchors.centerIn : parent source : "qrc:/images/iStepCheck" fillMode : Image.PreserveAspectFit - visible : _root.complete + visible : _root.complete && _root.showCompleteCheck } // this text is created only for the maximum(current) font info(height) Index: sources/gui/qml/components/StepIndicator.qml =================================================================== diff -u -r70d72796067d8a626458328e2642ab3e2b033648 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/components/StepIndicator.qml (.../StepIndicator.qml) (revision 70d72796067d8a626458328e2642ab3e2b033648) +++ sources/gui/qml/components/StepIndicator.qml (.../StepIndicator.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -37,9 +37,12 @@ property int currentStepIndex : 0 property int diameter : 15 + property int subStepIndex : 0 + property int subStepsLength : 0 + width : _gridSteps.width height : _gridSteps.height - color : Colors.backgroundMain + color : Colors.transparent QtObject { id: _private property string stepNamesFirst: "" @@ -109,8 +112,22 @@ hideLabels : _root.hideLabels vertical : _root.vertical text : modelData - complete : currentStepIndex > 0 && index < currentStepIndex - 1 // first index is used for the head/first bullet - current : currentStepIndex > 0 && index == currentStepIndex - 1 // first index is used for the head/first bullet + complete : currentStepIndex > 0 && index < currentStepIndex - 1 // first index is used for the head/first bullet + current : currentStepIndex > 0 && index === currentStepIndex - 1 // first index is used for the head/first bullet + + SubStepIndicator { id: _subStep + anchors { + top : parent.bottom + topMargin : 25 + horizontalCenter: parent.horizontalCenter + } + + subStepIndex : _root.subStepIndex + subStepsLength : _root.subStepsLength + height : 10 + width : _nextStepsBullet.width * _root.subStepsLength + visible : _nextStepsBullet.current && _root.subStepsLength > 0 + } } } } Index: sources/gui/qml/components/SubStepIndicator.qml =================================================================== diff -u --- sources/gui/qml/components/SubStepIndicator.qml (revision 0) +++ sources/gui/qml/components/SubStepIndicator.qml (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -0,0 +1,46 @@ +// Qt +import QtQuick 2.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" + +Rectangle { id: _root + color : Colors.transparent + width : _row.width + height : _row.height + + property int subStepIndex : 0 + property int subStepsLength : 0 + property int spacing : 5 + + Row { id: _row + spacing: 5 + anchors.centerIn: parent + + Repeater { id: _tailStepsRepeater + model: _root.subStepsLength + + Grid { id: _gridStepsRest + rows : 1 + columns : 0 + rowSpacing : _root.spacing + columnSpacing : _root.spacing + verticalItemAlignment : Grid.AlignVCenter + horizontalItemAlignment : Grid.AlignHCenter + + Line { id : _spacerLine + color : _nextStepsBullet.color + visible : index !== 0 // do not show fist line onl lines inbetween bullets + } + StepBullet { id: _nextStepsBullet + complete : _root.subStepIndex > 0 && index < _root.subStepIndex - 1 // first index is used for the head/first bullet + current : _root.subStepIndex > 0 && index === _root.subStepIndex - 1 // first index is used for the head/first bullet + showCompleteCheck : false + diameter : 13 + } + } + } + } +} Index: sources/gui/qml/components/TimeCircle.qml =================================================================== diff -u -ra5760947d3ed0d2748ba023a1c25e3c6aa0b1de1 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/components/TimeCircle.qml (.../TimeCircle.qml) (revision a5760947d3ed0d2748ba023a1c25e3c6aa0b1de1) +++ sources/gui/qml/components/TimeCircle.qml (.../TimeCircle.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -45,10 +45,11 @@ height : diameter ProgressCircle { id: _progressCircle - minimum : _root.minimum - maximum : _root.maximum - anchors.centerIn: parent - value : _root.progressValue + minimum : _root.minimum + maximum : _root.maximum + anchors.fill : parent + value : _root.progressValue + circleShadowColor : Colors.mainTreatmentLighterBlue TimeText { id: _timeText Behavior on opacity { OpacityAnimator { duration: 1000 } } Index: sources/gui/qml/components/WaitDone.qml =================================================================== diff -u -ra5760947d3ed0d2748ba023a1c25e3c6aa0b1de1 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/components/WaitDone.qml (.../WaitDone.qml) (revision a5760947d3ed0d2748ba023a1c25e3c6aa0b1de1) +++ sources/gui/qml/components/WaitDone.qml (.../WaitDone.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -36,6 +36,9 @@ height : _root.diameter opacity : ! _root.done ? 1 : 0 source : "qrc:/images/iBusy" + fillMode: Image.PreserveAspectFit + mipmap : true + smooth : true RotationAnimator on rotation { running : ! _root.done && ! _root.pause @@ -50,9 +53,13 @@ Image { id: _checkIndicator anchors.centerIn: _root opacity : _root.done ? 1 : 0 - width : _root.diameter + 15 - height : _root.diameter + 15 + width : _root.diameter + height : _root.diameter source : fail ? "qrc:/images/iBusyFail" : "qrc:/images/iBusyDone" + fillMode: Image.PreserveAspectFit + mipmap : true + Behavior on opacity { OpacityAnimator { duration: 1200 } } + } } Index: sources/gui/qml/compounds/CheckListView.qml =================================================================== diff -u -ra5760947d3ed0d2748ba023a1c25e3c6aa0b1de1 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/compounds/CheckListView.qml (.../CheckListView.qml) (revision a5760947d3ed0d2748ba023a1c25e3c6aa0b1de1) +++ sources/gui/qml/compounds/CheckListView.qml (.../CheckListView.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -52,6 +52,9 @@ function setClear (vModel) { vModel.stepStart = false ; vModel.stepDone = false } function setWait (vModel) { vModel.stepStart = true ; vModel.stepDone = false } function setDone (vModel) { vModel.stepStart = true ; vModel.stepDone = true } + + function stepDone (vIndex) { setDone (_listView.itemAt(vIndex)) } + function setItemExt (vIndex, vEntered) { let goBak = pIndex > vIndex let goTop = pIndex < vIndex @@ -139,12 +142,14 @@ verticalAlignment: Text.AlignVCenter text : modelData anchors.fill: parent - color : Colors.textMain + color : Colors.offWhite font.pixelSize: Fonts.fontPixelStateListText } Line { id: _separatorLine length : _delegate.width + 2 * linePad - thickness : 2 + thickness : 1 + color : Colors.checkListLine + opacity : 0.5 anchors { bottom : _delegate.bottom left : _delegate.left Index: sources/gui/qml/compounds/InstructionView.qml =================================================================== diff -u -ra9557e00ee75086bc640cb28ab4899ea4affa9ff -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/compounds/InstructionView.qml (.../InstructionView.qml) (revision a9557e00ee75086bc640cb28ab4899ea4affa9ff) +++ sources/gui/qml/compounds/InstructionView.qml (.../InstructionView.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -26,7 +26,6 @@ property var stepNames : [] property var stepImages : [] property int currentIndex : 0 - readonly property bool isEmpty : stepNames.length == 0 && stepImages.length == 0 color : Colors.offWhite radius : Variables.alarmDialogRadius @@ -57,7 +56,7 @@ anchors.top : parent.top anchors.topMargin : Variables.defaultMargin * 2 spacing : 5 - width : parent.width * 2/3 + width : parent.width / 2 Repeater { id: _instrutionSteps model: _root.stepNames @@ -92,7 +91,7 @@ verticalCenter : parent.verticalCenter } text : _root.stepNames.length ? _root.stepNames[index] : "" - font.weight : index === _root.currentIndex ? Font.DemiBold : Font.Normal + font.weight : index === _root.currentIndex ? Font.Medium : Font.Normal color : index === _root.currentIndex ? "#18559E" : Colors.alarmDialogText wrapMode : Text.WordWrap font.pixelSize : Fonts.fontPixelInstructionStep Index: sources/gui/qml/compounds/StepNavigationTitleBar.qml =================================================================== diff -u -rbed87eff8cfc2398d00eb62651c165f014880a1a -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/compounds/StepNavigationTitleBar.qml (.../StepNavigationTitleBar.qml) (revision bed87eff8cfc2398d00eb62651c165f014880a1a) +++ sources/gui/qml/compounds/StepNavigationTitleBar.qml (.../StepNavigationTitleBar.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -26,6 +26,9 @@ */ Rectangle { id: _root property int stepIndex : 0 + property int subStepIndex : 0 + property int subStepsLength : 0 + property int stepLineLength : 125 property var stepNames : [] property alias backVisible : _backButton .visible @@ -65,6 +68,8 @@ currentStepIndex: _root.stepIndex spacerLineLength: _root.stepLineLength stepNames : _root.stepNames + subStepIndex : _root.subStepIndex + subStepsLength : _root.subStepsLength } } } Index: sources/gui/qml/dialogs/diagnostics/DiagnosticsSwipe.qml =================================================================== diff -u -rb80f8f84f21f86ad4c962a2c690447c572498e0b -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/dialogs/diagnostics/DiagnosticsSwipe.qml (.../DiagnosticsSwipe.qml) (revision b80f8f84f21f86ad4c962a2c690447c572498e0b) +++ sources/gui/qml/dialogs/diagnostics/DiagnosticsSwipe.qml (.../DiagnosticsSwipe.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -21,7 +21,6 @@ import "qrc:/globals" import "qrc:/components" import "qrc:/dialogs" -import "qrc:/pages/pretreatment/connection" /*! * \brief the pre treatment prime stack screen */ Index: sources/gui/qml/globals/Colors.qml =================================================================== diff -u -r232dc65ad1d642f750547db6c480da534704a2c4 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/globals/Colors.qml (.../Colors.qml) (revision 232dc65ad1d642f750547db6c480da534704a2c4) +++ sources/gui/qml/globals/Colors.qml (.../Colors.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -37,7 +37,7 @@ readonly property color backgroundButtonNormal : transparent readonly property color backgroundButtonSelect : "#438FEB" readonly property color backgroundButtonSelectDark : "#135088" // "#214773" - readonly property color backgroundDialog : "#254670" + readonly property color backgroundDialog : "#1B3F66" readonly property color backgroundMenu : "#14314C" readonly property color backgroundMainMenu : "#0F2841" //// ----- @LEAHIZED readonly property color backgroundDottedMenu : "#64809D" @@ -106,6 +106,7 @@ readonly property color textTextRectExtra : "#708795" readonly property color line : "#094266" + readonly property color checkListLine : "#4E74A3" readonly property color pressuresText : white readonly property color pressuresArterialBar : "#FF8282" @@ -165,6 +166,8 @@ readonly property color roFeatured : "#E79DF6" readonly property color roDefeatured : "#F9CD74" + readonly property color waterSampleContainer : "#2A425A" + // ---------- < PRS > Related Section ---------- // Alarm priority colors function alarmPriorityColors(vPriority) { Index: sources/gui/qml/globals/Fonts.qml =================================================================== diff -u -r41ba9331e6a540df0c8eced0c4d3b8684afa9afa -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/globals/Fonts.qml (.../Fonts.qml) (revision 41ba9331e6a540df0c8eced0c4d3b8684afa9afa) +++ sources/gui/qml/globals/Fonts.qml (.../Fonts.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -75,8 +75,8 @@ readonly property int fontPixelDurationCurTime : 89 readonly property int fontPixelDurationAdjTime : 28 - readonly property int fontPixelStateListText : 20 - readonly property int fontPixelCirclProgressTimeSmall : 32 + readonly property int fontPixelStateListText : 24 + readonly property int fontPixelCirclProgressTimeSmall : 50 readonly property int fontPixelCirclProgressTimeNormal : 90 readonly property int fontPixelUltrafiltrationAdjustmentMetrics : 30 Index: sources/gui/qml/globals/Variables.qml =================================================================== diff -u -r0dfba44fb7172b9458d161b3ed5f54527f93b698 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/globals/Variables.qml (.../Variables.qml) (revision 0dfba44fb7172b9458d161b3ed5f54527f93b698) +++ sources/gui/qml/globals/Variables.qml (.../Variables.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -42,7 +42,7 @@ readonly property int mainMenuHeight : 80 //// ----- @LEAHIZED readonly property int alarmDialogHeaderHeight : 100 - readonly property int instructionHeight : 73 + readonly property int instructionHeight : 77 readonly property int minVGap : 15 readonly property int minVGap2 : 30 @@ -102,7 +102,7 @@ readonly property int circleNormalDiameter : 418 readonly property int progressCircleDiameterNormal : circleNormalDiameter - readonly property int progressCircleDiameterSmall : 150 + readonly property int progressCircleDiameterSmall : 250 readonly property int opacityAnimationDuration : 1200 readonly property int sliderTextMargin : 20 @@ -111,7 +111,7 @@ readonly property int notificationHeight : 80 //// ----- @LEAHIZED readonly property int notificationIconDiameter : 36 - readonly property int checkListViewItemWidth : 350 + readonly property int checkListViewItemWidth : 400 readonly property int checkListViewItemHeight : 60 readonly property int pauseIconDiameter : 60 @@ -257,6 +257,9 @@ // Calcium readonly property int substitutionPrecision : 1 + // conductivity + readonly property int conductivityPrecision : 1 + function sizeConverted(vSize, vSizePowers, vRound = 2) { return ( vSize / vSizePowers // convert from byte to Giga byte @@ -287,6 +290,8 @@ readonly property string preTreatmentStepLabelPriming : qsTr("PRIME" ) readonly property string preTreatmentStepLabelUltrafiltration : qsTr("BEGIN" ) + readonly property string unitTextChlorine : qsTr("mg/L") + // Heparin readonly property string unitHeparinType : qsTr("IU/mL") // Units Index: sources/gui/qml/main.qml =================================================================== diff -u -rc9764bd0ad823c5c1725d7c7f556290c2c459d4d -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/main.qml (.../main.qml) (revision c9764bd0ad823c5c1725d7c7f556290c2c459d4d) +++ sources/gui/qml/main.qml (.../main.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -361,6 +361,10 @@ function onStandbyWaitDisinfectChanged ( vValue ) { _mainMenu.isTreatment() } } + Connections { target: _mainStack + function onIsCreateRx ( vState ) { _headerBar.isCreateRx = vState } + } + // 9 - Others HeaderBar { id: _headerBar anchors.top: parent.top Index: sources/gui/qml/pages/MainStack.qml =================================================================== diff -u -r0dfba44fb7172b9458d161b3ed5f54527f93b698 -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/pages/MainStack.qml (.../MainStack.qml) (revision 0dfba44fb7172b9458d161b3ed5f54527f93b698) +++ sources/gui/qml/pages/MainStack.qml (.../MainStack.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -41,12 +41,16 @@ property var currentScreen: stackView.currentItem + signal isCreateRx(bool vState) // pass upstream to HeaderBar + stackView.initialItem : _root.initialItem // Standby / Disinfection DisinfectStack { id: _disinfectStack } // Pre Treatment - PreTreatmentStack { id: _preTreatmentStack } + PreTreatmentStack { id: _preTreatmentStack + onIsCreateRxChanged : _root.isCreateRx(_preTreatmentStack.isCreateRx) + } // In TreatmentStack TreatmentStack { id: _treatmentStack } Index: sources/gui/qml/pages/TreatmentFlowBase.qml =================================================================== diff -u -r41ba9331e6a540df0c8eced0c4d3b8684afa9afa -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/pages/TreatmentFlowBase.qml (.../TreatmentFlowBase.qml) (revision 41ba9331e6a540df0c8eced0c4d3b8684afa9afa) +++ sources/gui/qml/pages/TreatmentFlowBase.qml (.../TreatmentFlowBase.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -39,6 +39,7 @@ property string instructionTitle : "" property var instructionStepNames : [] property var instructionStepImages : [] + property string subStepName : "" // used for instructions with miltiple sub steps property bool hasTimeCircle : false readonly property alias timeCircle : _timeCircleLoader.item @@ -59,7 +60,7 @@ property bool isComplete : false - readonly property int titleTopMargin: 110 + property int titleTopMargin: 110 readonly property int sideMargins : Variables.defaultMargin * 2 + Variables.headerButtonsMargin // matching header button margins signal backClicked() @@ -138,16 +139,16 @@ maximum : _root.timeCircleMaximum progressValue : _root.timeCircleProgressValue timeTextValue : _root.timeCircleTimeTextValue - thickness : _root.hasCheckList ? 1 : 2 + thickness : 15 diameter : _root.hasCheckList ? Variables.progressCircleDiameterSmall : Variables.progressCircleDiameterNormal timeTextPixelSize : _root.hasCheckList ? Fonts.fontPixelCirclProgressTimeSmall : Fonts.fontPixelCirclProgressTimeNormal } } Loader { id: _checkListLoader active : _root.hasCheckList - anchors.top : _root.hasTimeCircle ? _timeCircleLoader.bottom : undefined - anchors.topMargin : _root.hasTimeCircle ? 25 : 0 + anchors.top : _root.hasTimeCircle ? _timeCircleLoader.bottom : undefined + anchors.topMargin : _root.hasTimeCircle ? Variables.defaultMargin * 2 : 0 anchors.horizontalCenter: _root.horizontalCenter anchors.centerIn : ! _root.hasTimeCircle ? parent : undefined width : Variables.checkListViewItemWidth @@ -175,22 +176,4 @@ } NotificationBarSmall { id: _notification } - - Connections { target: vSettings - function onInstructionsChanged ( vValue ) { - if ( instructionBased ) { - let stepName = header.stepNames[stackStepIndex] - if ( stepName === undefined ) stepName = "" - let group = vSettings.groupFormat.arg(stepName).arg(title.text) - let instructionsGroup = vSettings.instructions[group] - if ( instructionsGroup !== undefined ) { - // DEBUG : - // console.debug(" 00000 ", group, settingsGroup, settingsCategory.groups) - _root.instructionTitle = instructionsGroup.title - _root.instructionStepNames = instructionsGroup.keys - _root.instructionStepImages = instructionsGroup.values - } - } - } - } } Index: sources/gui/qml/pages/posttreatment/PostTreatmentStack.qml =================================================================== diff -u -rbed87eff8cfc2398d00eb62651c165f014880a1a -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/pages/posttreatment/PostTreatmentStack.qml (.../PostTreatmentStack.qml) (revision bed87eff8cfc2398d00eb62651c165f014880a1a) +++ sources/gui/qml/pages/posttreatment/PostTreatmentStack.qml (.../PostTreatmentStack.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -100,7 +100,7 @@ function confirmButtonText() { switch ( _root.stackStepIndex ) { case PostTreatmentStack.Disconnection: - return qsTr("Auto-Eject") + return qsTr("Auto Eject") case PostTreatmentStack.Review: return qsTr("NEXT") case PostTreatmentStack.Disinfection: @@ -187,32 +187,32 @@ Connections { target: vPostTreatmentAdjustmentPatientDisconnectionConfirm function onAdjustmentTriggered ( vValue ) { if ( vPostTreatmentAdjustmentPatientDisconnectionConfirm.adjustment_Accepted ) { - _treatmentReviewConfirm.informationText = "" + _treatmentReviewConfirm.reasonText = "" page( _disposablesRemovalConfirm ) } else { - _treatmentReviewConfirm.informationText = vPostTreatmentAdjustmentPatientDisconnectionConfirm.text() + _treatmentReviewConfirm.reasonText = vPostTreatmentAdjustmentPatientDisconnectionConfirm.text() } } } Connections { target: vPostTreatmentAdjustmentDisposablesRemovalConfirm function onAdjustmentTriggered ( vValue ) { if ( vPostTreatmentAdjustmentDisposablesRemovalConfirm.adjustment_Accepted ) { - _patientDisconnectionConfirm.informationText = "" + _patientDisconnectionConfirm.reasonText = "" page( _treatmentReviewConfirm ) } else { - _patientDisconnectionConfirm.informationText = vPostTreatmentAdjustmentDisposablesRemovalConfirm.text() + _patientDisconnectionConfirm.reasonText = vPostTreatmentAdjustmentDisposablesRemovalConfirm.text() } } } Connections { target: vPostTreatmentAdjustmentTreatmentLog function onAdjustmentTriggered ( vValue ) { if ( vPostTreatmentAdjustmentTreatmentLog.adjustment_Accepted ) { - _treatmentReviewConfirm.informationText = "" + _treatmentReviewConfirm.reasonText = "" } else { - _treatmentReviewConfirm.informationText = vPostTreatmentAdjustmentTreatmentLog.text() + _treatmentReviewConfirm.reasonText = vPostTreatmentAdjustmentTreatmentLog.text() } } } Index: sources/gui/qml/pages/pretreatment/PreTreatmentBase.qml =================================================================== diff -u -r8457901952a1d732c4688da471ae98e1d4f3024f -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/pages/pretreatment/PreTreatmentBase.qml (.../PreTreatmentBase.qml) (revision 8457901952a1d732c4688da471ae98e1d4f3024f) +++ sources/gui/qml/pages/pretreatment/PreTreatmentBase.qml (.../PreTreatmentBase.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -31,11 +31,44 @@ onVisibleChanged: if ( visible ) { _root.updateModel() } + /// --------TODO REMOVE -- DEMO testing progression --------------------------//// + // TODO remove -- testing progress ////////////////////////// + property int testCount : checkListStepNames.length + property int increment : timeCircleMaximum / checkListStepNames.length + property int step : 1 + + function resetTest() { + timeCircleProgressValue = 0 + step = 1 + checkList.setItemExt(0, true) + _progressTimer.start() + } + + function incrementTest() { + if (timeCircleProgressValue >= timeCircleMaximum ) { return } + timeCircleProgressValue = step * increment + + // fix setItemExt methods in checklist later.. i do not understand 😵‍💫 + checkList.setItemExt(step, true) + checkList.stepDone(step - 1) + step++ + } + + Timer { id: _progressTimer + interval : 1000 + running : ! isComplete + repeat : ! isComplete + onTriggered: incrementTest() + } + /// --------END REMOVE -----------------------------------------------------//// + + // update model for instruction based steps function updateModel () { let stepName = stepNames[stackStepIndex] if ( stepName === undefined ) stepName = "" - let group = vSettings.advancedMode ? vSettings.groupFormat.arg(stepName).arg("Advanced") : stepName + let group = vSettings.advancedMode ? vSettings.groupFormat.arg(stepName).arg("Advanced") : + _root.subStepName.length === 0 ? stepName : vSettings.groupFormat.arg(stepName).arg(_root.subStepName) let instructionsGroup = vSettings.instructions[group] if ( instructionsGroup !== undefined ) { Fisheye: Tag 4a2b83dcb56555861d2c741a8e8894e5b07e24bf refers to a dead (removed) revision in file `sources/gui/qml/pages/pretreatment/PreTreatmentConsumablesStack.qml'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/gui/qml/pages/pretreatment/PreTreatmentInstallStack.qml =================================================================== diff -u --- sources/gui/qml/pages/pretreatment/PreTreatmentInstallStack.qml (revision 0) +++ sources/gui/qml/pages/pretreatment/PreTreatmentInstallStack.qml (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -0,0 +1,109 @@ + +// Qt +import QtQuick 2.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" +import "qrc:/pages/pretreatment" + +/*! + * \brief the pre treatment water sample stack screen + */ +StackItem { id: _root + stackView.initialItem : null + + enum Step { + BloodSetTubing , + BloodLines , + PressureLinesAndDialyzer, + SubStepCount + } + + property int subStepIndex: PreTreatmentInstallStack.Step.BloodSetTubing + + signal goToNextStep() + signal goToPreviousStep() + + function initStack() { page ( _preTreatmentBloodSetTubing ) } + + function continueClicked() { + switch ( _root.subStepIndex ) { + case PreTreatmentInstallStack.Step.BloodSetTubing: + vPreTreatmentAdjustmentDisposablesConfirm.doConfirm() + break + case PreTreatmentInstallStack.Step.BloodLines: + page ( _preTreatmentPressureLinesAndDialyzer ) + break + case PreTreatmentInstallStack.Step.PressureLinesAndDialyzer: + goToNextStep () + break + default: + break + } + } + + function backClicked() { + switch ( _root.subStepIndex ) { + case PreTreatmentInstallStack.Step.BloodSetTubing: + goToPreviousStep () + break + case PreTreatmentInstallStack.Step.BloodLines: + // cannot go back from here + break + case PreTreatmentInstallStack.Step.PressureLinesAndDialyzer: + page ( _preTreatmentBloodLines ) + break + default: + break + } + } + + function confirmButtonText() { + switch ( _root.subStepIndex ) { + case PreTreatmentInstallStack.Step.BloodSetTubing: + return qsTr("Auto Load") + case PreTreatmentInstallStack.Step.BloodLines: + case PreTreatmentInstallStack.Step.PressureLinesAndDialyzer: // fall through + default: + return qsTr("Next") + } + } + + function backEnabled() { + return subStepIndex !== PreTreatmentInstallStack.Step.BloodLines + } + + // ----- Screens definitions + PreTreatmentBase { id: _preTreatmentBloodSetTubing + instructionBased : true + onVisibleChanged : if (visible) { _root.subStepIndex = PreTreatmentInstallStack.Step.BloodSetTubing ; updateModel() } + subStepName : qsTr("Blood Tubing Set") + } + + PreTreatmentBase { id: _preTreatmentBloodLines + instructionBased : true + onVisibleChanged : if (visible) { _root.subStepIndex = PreTreatmentInstallStack.Step.BloodLines ; updateModel() } + subStepName : qsTr("Bloodlines") + } + + PreTreatmentBase { id: _preTreatmentPressureLinesAndDialyzer + instructionBased : true + onVisibleChanged : if (visible) { _root.subStepIndex = PreTreatmentInstallStack.Step.PressureLinesAndDialyzer ; updateModel()} + subStepName : qsTr("Pressure Lines and Dialyzer") + } + + // blood tubing set auto-load + Connections { target: vPreTreatmentAdjustmentDisposablesConfirm + function onAdjustmentTriggered ( vValue ) { + if ( vPreTreatmentAdjustmentDisposablesConfirm.adjustment_Accepted ) { + _preTreatmentBloodSetTubing.reasonText = "" + if ( vSettings.advancedMode ) { goToNextStep () } + else { page ( _preTreatmentBloodLines ) } + } else { + _preTreatmentBloodSetTubing.reasonText = vPreTreatmentAdjustmentDisposablesConfirm.text() + } + } + } +} Index: sources/gui/qml/pages/pretreatment/PreTreatmentPrime.qml =================================================================== diff -u --- sources/gui/qml/pages/pretreatment/PreTreatmentPrime.qml (revision 0) +++ sources/gui/qml/pages/pretreatment/PreTreatmentPrime.qml (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -0,0 +1,107 @@ +/*! + * + * Copyright (c) 2021-2024 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 PreTreatmentPrime.qml + * \author (last) Behrouz NematiPour + * \date (last) 31-Aug-2023 + * \author (original) Behrouz NematiPour + * \date (original) 01-Mar-2021 + * + */ + +// Qt +import QtQuick 2.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" +import "qrc:/pages/pretreatment" + +/*! + * \brief The Pre Tretreatment Prime Screen + */ +PreTreatmentBase { id: _root + objectName: "_PreTreatmentPrime" + isComplete : timeCircleProgressValue >= timeCircleMaximum // TODO Update later + completeText : qsTr("Priming Complete!") + + // time circle + hasTimeCircle : true + timeCircleMinimum : 0 + timeCircleMaximum : 3 * 60 // vPreTreatmentDisposablesPrime.total + timeCircleProgressValue : 0 // vPreTreatmentDisposablesPrime.elapsed + timeCircleTimeTextValue : timeCircleProgressValue * 60 // vPreTreatmentDisposablesPrime.remaining * 60 + + // chcek list + hasCheckList : true + checkListStepNames : [ + qsTr("Blood Tubing Circuit Priming" ), + qsTr("Dialysate Circuit Priming" ), + ] + + +// Connections { target: vPreTreatmentStates +// function onSelfTestDryChanged ( vValue ) { page( _preTreatmentDrySelfTest , vValue )} +// function onSelfTestDry_startChanged ( vValue ) { _preTreatmentDrySelfTest .checkList.setItemExt(0, true )} +// function onSelfTestDry_waitDoorCloseChanged ( vValue ) { _preTreatmentDrySelfTest .checkList.setItemExt(0, vValue )} +// function onSelfTestDry_usedCartridgeEntered ( vValue ) { _preTreatmentDrySelfTest .checkList.setItemExt(1, true )} +// function onSelfTestDry_cartridgeLoadedEntered ( vValue ) { _preTreatmentDrySelfTest .checkList.setItemExt(1, vValue )} +// function onSelfTestDry_pressureSensorsNormalSetupEntered ( vValue ) { _preTreatmentDrySelfTest .checkList.setItemExt(2, true )} +// function onSelfTestDry_pressureSensorsVenousSetupEntered ( vValue ) {} +// function onSelfTestDry_pressureSensorsVenousEntered ( vValue ) {} +// function onSelfTestDry_pressureSensorsArterialSetupEntered ( vValue ) {} +// function onSelfTestDry_pressureSensorsArterialEntered ( vValue ) {} +// function onSelfTestDry_pressureSensorsDecayEntered ( vValue ) {} +// function onSelfTestDry_pressureSensorsStabilityEntered ( vValue ) {} +// function onSelfTestDry_pressureSensorsNormalEntered ( vValue ) { _preTreatmentDrySelfTest .checkList.setItemExt(2, vValue )} +// function onSelfTestDry_syringePumpEntered ( vValue ) { _preTreatmentDrySelfTest .checkList.setItemExt(3, vValue )} +// function onSelfTestDry_syringePumpOcclusionDetectionEntered ( vValue ) { _preTreatmentDrySelfTest .checkList.setItemExt(4, vValue )} +// function onSelfTestDry_stoppedEntered ( vValue ) {} +// function onSelfTestDry_completeEntered ( vValue ) {} +// } + +// Connections { target: vPreTreatmentStates +// function onPrimeChanged ( vValue ) { page( _preTreatmentDisposablesPrime , vValue )} +// function onPrime_waitUserStartEntered ( vValue ) {} +// function onPrime_salineSetupEntered ( vValue ) {} +// function onPrime_salinePurgeAirEntered ( vValue ) {} +// function onPrime_salineCirculateBloodCircuitEntered ( vValue ) {} +// function onPrime_reservoirOneFillCompleteEntered ( vValue ) {} +// function onPrime_dialysateDialyzerEntered ( vValue ) {} +// function onPrime_salineDialyzerSetupEntered ( vValue ) {} +// function onPrime_salineDialyzerEntered ( vValue ) {} +// function onPrime_reservoirTwoFillCompleteEntered ( vValue ) {} +// function onPrime_dialysateBypassEntered ( vValue ) {} +// function onPrime_wetSelfTestsEntered ( vValue ) {} +// function onPrime_pauseEntered ( vValue ) {} +// function onPrime_completeEntered ( vValue ) {} + +// //TODO this way of handling the states are new for states which can reset to the previous states +// // if it is successfull I may use everywhere. +// // 1 - it uses new setItemExt +// // 2 - bundles the states of FW in UI states +// // setitem differences. +// // old: +// // 1 - the start FW state of the UI state set to true +// // 2 - the end FW state fo the UI state set with vValue +// // 3 - nothing for the FW in-states of the UI states +// // new: +// // - all set with vValue and use the setItemExt +// // Unkown missbehavior: +// // - the only misbehavior is if the FW changes the FW state in the middle (in one of in-states), +// // since UI budles the FW states, it assumes it is done and checks the state which may not be ideal. +// // as an example if during the Dyalysate FW changes th state to the pause, UI may not show the Dialysaate done (probably!). +// function onPrime__BloodCircuitEntered ( vValue ) { _preTreatmentDisposablesPrime .checkList.setItemExt(0, vValue )} +// function onPrime__DialysateCircuitEntered ( vValue ) { _preTreatmentDisposablesPrime .checkList.setItemExt(1, vValue )} +// function onPrime__WetSelfTestsEntered ( vValue ) { _preTreatmentDisposablesPrime .checkList.setItemExt(2, vValue )} +// } + + + + +} Fisheye: Tag 4a2b83dcb56555861d2c741a8e8894e5b07e24bf refers to a dead (removed) revision in file `sources/gui/qml/pages/pretreatment/PreTreatmentPrimeStack.qml'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/gui/qml/pages/pretreatment/PreTreatmentSelfTests.qml =================================================================== diff -u --- sources/gui/qml/pages/pretreatment/PreTreatmentSelfTests.qml (revision 0) +++ sources/gui/qml/pages/pretreatment/PreTreatmentSelfTests.qml (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -0,0 +1,57 @@ +/*! + * + * Copyright (c) 2021-2024 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 PreTreatmentSelfTests.qml + * \author (last) Behrouz NematiPour + * \date (last) 31-Aug-2023 + * \author (original) Behrouz NematiPour + * \date (original) 18-Mar-2021 + * + */ + +// Qt +import QtQuick 2.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" +import "qrc:/pages/pretreatment" + +/*! + * \brief the pre-treatment self tests screen + */ +PreTreatmentBase { id: _root + isComplete : timeCircleProgressValue >= timeCircleMaximum //vPreTreatmentStates.selfTestConsumables_complete + completeText : qsTr("Self Test Complete!") + + // time circle + hasTimeCircle : true + timeCircleMinimum : 0 + timeCircleMaximum : 30 + timeCircleProgressValue : 0 + timeCircleTimeTextValue : timeCircleProgressValue * 60 + + // check List + hasCheckList : true + checkListStepNames : [ + qsTr("Auto-Load Blood Tubing" ), + qsTr("Cartridge Install Checks" ), + qsTr("Pressure Leak Check" ), + + ] + + +// TODO FIXME +// Connections { target: vPreTreatmentStates +// function onSelfTestConsumables_installChanged ( vValue ) { page( _preTreatmentConsumablesInstall , vValue )} +// function onselfTestConsumables_primeEntered ( vValue ) {/* _preTreatmentConsumablesSelfTest.checkList.setItemExt( 0, vValue )*/ } +// function onSelfTestConsumables_biCarbPumpEntered ( vValue ) { _preTreatmentConsumablesSelfTest.checkList.setItemExt( 0, vValue )} +// function onSelfTestConsumables_acidPumpEntered ( vValue ) { _preTreatmentConsumablesSelfTest.checkList.setItemExt( 1, vValue )} +// } + +} Index: sources/gui/qml/pages/pretreatment/PreTreatmentStack.qml =================================================================== diff -u -re6f122cd598d085faa3b1e295317d793a1dd9fcb -r4a2b83dcb56555861d2c741a8e8894e5b07e24bf --- sources/gui/qml/pages/pretreatment/PreTreatmentStack.qml (.../PreTreatmentStack.qml) (revision e6f122cd598d085faa3b1e295317d793a1dd9fcb) +++ sources/gui/qml/pages/pretreatment/PreTreatmentStack.qml (.../PreTreatmentStack.qml) (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -45,10 +45,10 @@ property var stepNames : [] // step name parallel list property var stepKeys : [] // step enum parallel list property int stackStepIndex : 0 + readonly property bool isInstall : stepKeys[_root.stackStepIndex] === PreTreatmentStack.Step.Installation readonly property bool isCreateRx : stepKeys[_root.stackStepIndex] === PreTreatmentStack.Step.CreateRx - readonly property bool isDialysteUf : stepKeys[_root.stackStepIndex] === PreTreatmentStack.Step.DialysateUF - // testing defeature... update later + // TODO testing defeature... update later property bool enableWaterSample : true onVisibleChanged: { @@ -97,7 +97,7 @@ values.push(qsTr("Rx")) keys.push(PreTreatmentStack.Step.DialysateUF) - values.push(qsTr("Dialysate/UF")) + values.push(qsTr("UF/Dialysate")) keys.push(PreTreatmentStack.Step.Connect) values.push(qsTr("Connect")) @@ -117,7 +117,9 @@ page ( _pretreatmentInstallation ) break case PreTreatmentStack.Step.Installation: - vPreTreatmentAdjustmentDisposablesConfirm.doConfirm() + if ( vSettings.advancedMode ) { vPreTreatmentAdjustmentDisposablesConfirm.doConfirm() } + else { _pretreatmentInstallation.continueClicked() } + break case PreTreatmentStack.Step.SelfTests: page ( _pretreatmentSaline ) @@ -126,21 +128,28 @@ page ( _pretreatmentPrime ) break case PreTreatmentStack.Step.Prime: + if ( _pretreatmentPrime.timeCircleProgressValue === 0 ) { vPreTreatmentAdjustmentDisposablesPrime.doPrime(); } + if ( ! _pretreatmentPrime.isComplete) { _pretreatmentPrime.incrementTest(); return; } // TODO update later only for testing + if ( enableWaterSample ) { page ( _pretreatmentWaterSample ) } else { page ( _pretreatmentCreate ) } break case PreTreatmentStack.Step.WaterSample: - page ( _pretreatmentCreate ) + vPreTreatmentAdjustmentWaterSample.doResult( _pretreatmentWaterSample.result ) + page ( _pretreatmentCreate ) // TODO remove when i do messaging break case PreTreatmentStack.Step.CreateRx: _pretreatmentCreate.confirmButtonClicked() if ( vTreatmentCreate.parametersValidated ) { page ( _pretreatmentDialysateUf ) } break case PreTreatmentStack.Step.DialysateUF: - page ( _pretreatmentConnect ) + vPreTreatmentAdjustmentUltrafiltrationInit.doAdjustment(_pretreatmentDialysateUf.ufVolume) + page ( _pretreatmentConnect ) // TODO remove when i do messaging break case PreTreatmentStack.Step.Connect: - // TODO Some FW request to enter Treatment mode + vPreTreatmentAdjustmentStartTreatment.doStart() + // TODO Keep for now until we figure out if this isnt going to be used anymore +// vPreTreatmentAdjustmentPatientConnectionConfirm.doConfirm() break default: break @@ -155,30 +164,8 @@ break case PreTreatmentStack.Step.Installation: if ( vSettings.advancedMode ) { vPreTreatmentAdjustmentInitTreatment.doCancel() } - else { page ( _pretreatmentConcentrates ) } + else { _pretreatmentInstallation.backClicked() } break - case PreTreatmentStack.Step.SelfTests: - page ( _pretreatmentInstallation ) - break - case PreTreatmentStack.Step.Saline: - page ( _pretreatmentSelfTests ) - break - case PreTreatmentStack.Step.Prime: - page ( _pretreatmentSaline ) - break - case PreTreatmentStack.Step.WaterSample: - page ( _pretreatmentPrime ) - break - case PreTreatmentStack.Step.CreateRx: - if ( enableWaterSample ) { page ( _pretreatmentWaterSample ) } - else { page ( _pretreatmentPrime ) } - break - case PreTreatmentStack.Step.DialysateUF: - // 🙅‍♂️ No going back - break - case PreTreatmentStack.Step.Connect: - page ( _pretreatmentDialysateUf ) - break default: break } @@ -187,19 +174,45 @@ // handle text for the confirm button on any pretreatment page function confirmButtonText() { switch ( stepKeys[_root.stackStepIndex] ) { - case PreTreatmentStack.Step.Concentrates: - return qsTr("Next") case PreTreatmentStack.Step.Installation: - return qsTr("Auto-Load") + return _pretreatmentInstallation.confirmButtonText() case PreTreatmentStack.Step.CreateRx: return vTreatmentCreate.parametersValidated - ? qsTr("CONFIRM") - : qsTr("VALIDATE") + ? qsTr("Confirm") + : qsTr("Validate") + case PreTreatmentStack.Step.Connect: + return qsTr("Start") default: return qsTr("Next") } } + function backEnabled() { + switch ( stepKeys[_root.stackStepIndex] ) { + case PreTreatmentStack.Step.Concentrates: + return true + case PreTreatmentStack.Step.Installation: + return _pretreatmentInstallation.backEnabled() + default: + return false // majority of pages back is disabled + } + } + + function confirmEnabled() { + switch ( stepKeys[_root.stackStepIndex] ) { + case PreTreatmentStack.Step.SelfTests: + return _pretreatmentSelfTests.isComplete + case PreTreatmentStack.Step.Prime: + return _pretreatmentPrime.isComplete + case PreTreatmentStack.Step.WaterSample: + return _pretreatmentWaterSample.confirmEnabled + case PreTreatmentStack.Step.CreateRx: + return _pretreatmentCreate.confirmReady() + default: + return true + } + } + // Header StepNavigationTitleBar { id: _titleBar stepIndex : _root.stackStepIndex @@ -212,10 +225,14 @@ } confirmText.text: confirmButtonText() confirmVisible : true - confirmEnabled : _root.isCreateRx ? _pretreatmentCreate.confirmReady() : true - backVisible : _root.isCreateRx ? ! vTreatmentCreate.parametersValidated : ! _root.isDialysteUf + confirmEnabled : _root.confirmEnabled() + backVisible : true + backEnabled : _root.backEnabled() width : _root.width stepNames : _root.stepNames + subStepIndex : isInstall ? _pretreatmentInstallation.subStepIndex + 1 : 0 + subStepsLength : isInstall ? PreTreatmentInstallStack.Step.SubStepCount : 0 + onBackClicked : _root.backClicked() onConfirmClicked: _root.confirmClicked() } @@ -226,71 +243,112 @@ onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.Concentrates); updateModel() } } - PreTreatmentBase { id: _pretreatmentInstallation - instructionBased : true - onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.Installation); updateModel() } + PreTreatmentInstallStack { id: _pretreatmentInstallation + onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.Installation); initStack() } } - PreTreatmentBase { id: _pretreatmentSelfTests - onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.SelfTests); } + PreTreatmentSelfTests{ id: _pretreatmentSelfTests + onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.SelfTests); resetTest() } } PreTreatmentBase { id: _pretreatmentSaline - onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.Saline); } + instructionBased : true + onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.Saline); updateModel() } } - PreTreatmentBase { id: _pretreatmentPrime - onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.Prime); } + PreTreatmentPrime { id: _pretreatmentPrime + onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.Prime); resetTest() } } - PreTreatmentBase { id: _pretreatmentWaterSample + PreTreatmentWaterSample { id: _pretreatmentWaterSample onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.WaterSample); } } PreTreatmentCreate { id: _pretreatmentCreate - onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.CreateRx) } + onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.CreateRx) } } - PreTreatmentBase { id: _pretreatmentDialysateUf - onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.DialysateUF); } + PreTreatmentUltrafiltration { id: _pretreatmentDialysateUf + onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.DialysateUF); } } PreTreatmentBase { id: _pretreatmentConnect - onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.Connect); } + instructionBased : true + onVisibleChanged : if (visible) { _root.stackStepIndex = stepKeys.indexOf(PreTreatmentStack.Step.Connect); updateModel() } } // Slots - Connections { target: vPreTreatmentAdjustmentDisposablesConfirm - function onAdjustmentTriggered ( vValue ) { - if ( vPreTreatmentAdjustmentDisposablesConfirm.adjustment_Accepted ) { - _pretreatmentInstallation.informationText = "" - page ( _pretreatmentSelfTests ) + Connections { target: vTDOpMode + function onPreTreatmentChanged( vValue ) { if ( vSettings.advancedMode ) { page ( _pretreatmentInstallation , vValue )} + else { page ( _pretreatmentConcentrates , vValue )} + } + } + + // Installation + Connections { target: _pretreatmentInstallation + function onGoToNextStep () { page ( _pretreatmentSelfTests )} + function onGoToPreviousStep () { page ( _pretreatmentConcentrates )} + } + + // priming + Connections { target: vPreTreatmentAdjustmentDisposablesPrime + function onAdjustmentTriggered ( vValue ) { + if ( vPreTreatmentAdjustmentDisposablesPrime.adjustment_Accepted ) { + _pretreatmentPrime.reasonText = "" } else { - _pretreatmentInstallation.informationText = vPreTreatmentAdjustmentDisposablesConfirm.text() + _pretreatmentPrime.reasonText = vPreTreatmentAdjustmentDisposablesPrime.text() } } } - Connections { target: vTDOpMode - function onPreTreatmentChanged( vValue ) { if ( vSettings.advancedMode ) { page ( _pretreatmentInstallation , vValue )} - else { page ( _pretreatmentConcentrates , vValue )} + // water sample + Connections { target: vPreTreatmentAdjustmentWaterSample + function onAdjustmentTriggered ( vValue ) { + if ( vPreTreatmentAdjustmentWaterSample.adjustment_Accepted ) { + _pretreatmentWaterSample.reasonText = "" + page ( _pretreatmentCreate ) + } else { + _pretreatmentWaterSample.reasonText = vPreTreatmentAdjustmentWaterSample.text() + } } } - // TODO in pre treatment story --- Clean up in pre treatment story -// PreTreatmentWaterSampleStack{ id: _preTreatmentWaterSampleStack ;objectName: "_preTreatmentWaterSampleStack" } -// PreTreatmentConsumablesStack{ id: _preTreatmentConsumablesStack ;objectName: "_preTreatmentConsumablesStack" } -// PreTreatmentPrimeStack { id: _pretreatmentPrimeStack ;objectName: "_pretreatmentPrimeStack" } -// PreTreatmentConnectionStack { id: _pretreatmentConnectionStack ;objectName: "_pretreatmentConnectionStack " } + // Ultrafiltration + Connections { target: vPreTreatmentAdjustmentUltrafiltrationInit + function onAdjustmentTriggered ( vValue ) { + // the maximum ultrafiltration volume has to be set/revert regardless + vTreatmentUltrafiltration.maximum = vPreTreatmentAdjustmentUltrafiltrationInit.volume -// Connections { target: vPreTreatmentStates -// function onWaterSampleChanged ( vValue ) { page( _preTreatmentWaterSampleStack , vValue )} -// function onSelfTestConsumablesChanged ( vValue ) { page( _preTreatmentConsumablesStack , vValue )} -// function onSelfTestNoCartridgeChanged ( vValue ) { page( _preTreatmentDisposablesStack , vValue )} -// function onInstallationChanged ( vValue ) { page( _preTreatmentDisposablesStack , vValue )} // DEBUG: Experimental : console.debug("vinstallation " -// function onSelfTestDryChanged ( vValue ) { page( _pretreatmentPrimeStack , vValue )} -// function onPrimeChanged ( vValue ) { page( _pretreatmentPrimeStack , vValue )} // DEBUG: Experimental : console.debug("vprime " -// function onRecirculateChanged ( vValue ) { page( _pretreatmentPrimeStack , vValue )} // DEBUG: Experimental : console.debug("vrecirculate " -// function onPatientConnectionChanged ( vValue ) { page( _pretreatmentConnectionStack , vValue )} + // but only if it has been accepted it will navigate + if ( vPreTreatmentAdjustmentUltrafiltrationInit.adjustment_Accepted ) { + page( _pretreatmentConnect ) + } + else { + _pretreatmentDialysateUf.reasonText = vPreTreatmentAdjustmentUltrafiltrationInit.text() + } + } + } + + // connect -- TODO Keep for now until we figure out if this isnt going to be used anymore +// Connections { target: vPreTreatmentAdjustmentPatientConnectionConfirm +// function onAdjustmentTriggered ( vValue ) { +// if ( vPreTreatmentAdjustmentPatientConnectionConfirm.adjustment_Accepted ) { +// page( _preTreatmentStartTreatment ) +// _pretreatmentConnect.informationText = "" +// } else { +// _pretreatmentConnect.informationText = vPreTreatmentAdjustmentPatientConnectionConfirm.text() +// } +// } // } + + // start treatment + Connections { target: vPreTreatmentAdjustmentStartTreatment + function onAdjustmentTriggered ( vValue ) { + if ( vPreTreatmentAdjustmentStartTreatment.adjustment_Accepted ) { + _pretreatmentConnect.reasonText = "" + } else { + _pretreatmentConnect.reasonText = vPreTreatmentAdjustmentStartTreatment.text() + } + } + } } Index: sources/gui/qml/pages/pretreatment/PreTreatmentUltrafiltration.qml =================================================================== diff -u --- sources/gui/qml/pages/pretreatment/PreTreatmentUltrafiltration.qml (revision 0) +++ sources/gui/qml/pages/pretreatment/PreTreatmentUltrafiltration.qml (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -0,0 +1,194 @@ +/*! + * + * Copyright (c) 2021-2024 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 PreTreatmentUltrafiltration.qml + * \author (last) Behrouz NematiPour + * \date (last) 08-Mar-2024 + * \author (original) Behrouz NematiPour + * \date (original) 18-Mar-2021 + * + */ + +// Qt +import QtQuick 2.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" +import "qrc:/compounds" +import "qrc:/pages/pretreatment" + +/*! + * \brief Pre-Treatment ultrafiltration screen + * \details which contains a slider to let user set the ultratiltration volume. + */ +PreTreatmentBase { id: _root + objectName: "_PreTreatmentUltrafiltration" + + readonly property alias ufVolume : _volumeGoalAdjuster.value + + // TODO in cleanup create shared UF qml component to use here and TreatmentAdjustmentUltrafiltrationEdit.qml -- this is all mostly same code + QtObject { id: _private + objectName: "_private" + readonly property real minimum : calculatePrecisionValue( vTreatmentRanges.treatmentRanges_Ultrafiltration_Volume_Min ) + readonly property real maximum : calculatePrecisionValue( vTreatmentRanges.treatmentRanges_Ultrafiltration_Volume_Max ) + readonly property real volumeRes : calculatePrecisionValue( vTreatmentRanges.ultrafiltrationVolumeRes ) + readonly property real setVolume : calculatePrecisionValue( vTreatmentUltrafiltration.setVolume ) + readonly property real volumeRemoved : calculatePrecisionValue( vTreatmentUltrafiltration.volumeRemoved ) + + readonly property int multiplier : Math.pow(10, Variables.ultrafiltrationPrecision) + function calculatePrecisionValue(value) { + return Math.round(value * multiplier) / multiplier + } + } + + Item { id: _contentArea + objectName: "_contentArea" + anchors { + top : _root.title.bottom + topMargin : Variables.defaultMargin * -1 //with current resolution this makes the screen look nice + horizontalCenter: parent.horizontalCenter + } + width : Variables.ultrafiltrationProgressBarWidth + + Column { id: _contentColumn + objectName : "_contentColumn" + anchors.fill: parent + width : parent.width + spacing : 80 + + Text { id: _ultrafiltrationTitle + color : Colors.textMain + font.pixelSize : Fonts.fontPixelContainerTitle + text : qsTr("Set Ultrafiltration Volume %1").arg(Variables.unitTextVolume) + anchors.horizontalCenter: parent.horizontalCenter + } + + ProgressBar { id: _maxVolumeBar + objectName : "_maxVolumeBar" + width : parent.width + height : 20 + marker.visible : false + bgColor : Colors.ufAdjustmentProgressBarBg + color : Colors.ufAdjustmentDeltaFill + radius : Variables.ultrafiltrationProgressBarRadius + minText { + font { + pixelSize : Fonts.fontPixelUltrafiltrationMinMaxLabel + weight : Font.Normal + } + color : Colors.progressBarMinMax + text : minimum.toFixed(Variables.ultrafiltrationPrecision) + " " + Variables.unitVolume + } + maxText { + font { + pixelSize : minText.font.pixelSize + weight : minText.font.weight + } + color : Colors.progressBarMinMax + text : _private.maximum.toFixed(Variables.ultrafiltrationPrecision) + " " + Variables.unitVolume + } + minimum : _private.minimum + maximum : _private.maximum + decimal : Variables.ultrafiltrationPrecision + value : _volumeGoalAdjuster.value + + Rectangle { id: _removedFill + objectName: "_removedFill" + anchors { + top : parent.top + bottom : parent.bottom + left : parent.left + } + z : parent.z + 1 + color : Colors.ufProgressBarFill + radius : parent.radius + } + } + + LabelUnitContainer { id: _volumeGoalContainer + objectName : "_volumeGoalContainer" + width : parent.width + height : Variables.adjustmentLabelUnitContainerHeight + text : qsTr("Ultrafiltration") + unitText : Variables.unitVolume + contentItem : ValueAdjuster { id: _volumeGoalAdjuster + objectName : "_volumeGoalAdjuster" + isActive : true + decimal : Variables.ultrafiltrationPrecision + minimum : Math.ceil(_private.volumeRemoved / step) * step + maximum : Math.floor(_private.maximum / step) * step + step : _private.volumeRes + value : { value = _private.setVolume } // set without binding + + onDidChange : { + value = _private.calculatePrecisionValue(vValue) + } + onMinimumChanged: { + if (value < minimum) { + value = minimum + } + } + onMaximumChanged: { + if (value > maximum) { + value = maximum + } + } + } + } + + Line { id: _divider + thickness : 2 + length : _root.width * .8 + color : Colors.checkListLine + opacity : 0.4 + anchors.horizontalCenter: parent.horizontalCenter + } + + Text { id: _dyalistateTitle + color : Colors.textMain + font.pixelSize : Fonts.fontPixelContainerTitle + text : qsTr("Test dialysate sample per your clinic's instructions") + anchors.horizontalCenter: parent.horizontalCenter + } + + Column { + spacing: 10 + width : parent.width + + LabelUnitContainer { id: _theoriticalCondictivityContainer + objectName : "_theoriticalCondictivityContainer" + width : parent.width + height : Variables.adjustmentLabelUnitContainerHeight + text : qsTr("Theoretical Conductivity") + unitText : Variables.unitTextDialCond + contentItem : Text { id: _theoriticalCondictivityText + anchors.centerIn: parent + text : "13.7" // TODO add actual value + color : Colors.offWhite + font.pixelSize : Fonts.fontPixelValueControl + } + } + + LabelUnitContainer { id: _independentConductivityReadingContainer + objectName : "_independentConductivityReadingContainer" + width : parent.width + height : Variables.adjustmentLabelUnitContainerHeight + text : qsTr("Independent Conductivity Reading") + unitText : Variables.unitTextDialCond + contentItem : Text { id: _independentConductivityReadingCText + anchors.centerIn: parent + text : "13.7" // TODO add actual value + color : Colors.offWhite + font.pixelSize : Fonts.fontPixelValueControl + } + } + } + } + } +} Index: sources/gui/qml/pages/pretreatment/PreTreatmentWaterSample.qml =================================================================== diff -u --- sources/gui/qml/pages/pretreatment/PreTreatmentWaterSample.qml (revision 0) +++ sources/gui/qml/pages/pretreatment/PreTreatmentWaterSample.qml (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -0,0 +1,127 @@ +/*! + * + * Copyright (c) 2021-2024 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 PreTreatmentWaterSampleStack.qml + * \author (last) Vy + * \date (last) 17-May-2023 + * \author (original) Behrouz NematiPour + * \date (original) 18-Mar-2021 + * + */ + +// Qt +import QtQuick 2.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" +import "qrc:/pages/pretreatment" + +/*! + * \brief the pre treatment water sample stack screen + */ +PreTreatmentBase { id: _root + objectName: "_PreTreatmentSampleStack" + + title.text : qsTr("Test the water sample per your clinic's instructions and select the result.") + title.font.pixelSize: Fonts.fontPixelSection + titleTopMargin : Variables.defaultMargin * 8 // with current resolution this makes the screen look nice + + readonly property bool confirmEnabled : _failContainer.selected || _passContainer.selected + readonly property bool result : _passContainer.selected + + onVisibleChanged: if ( visible ) { reset() } + + function reset() { + _failContainer.selected = false + _passContainer.selected = false + } + + component WaterSampleContainer: Rectangle { id: _waterSampleContainer + property bool selected : false + property alias imageSource : _resultImage.source + property alias buttonText : _button.textString + property alias description : _description.text + + signal clicked() + + color : Colors.waterSampleContainer + radius : Variables.touchRectRadius + width : 400 + height : 450 // with current resolution this makes the screen look nice + + border { + width : 2 + color : _waterSampleContainer.selected ? Colors.backgroundButtonSelect : Colors.waterSampleContainer + } + + Image { id: _resultImage + anchors { + top : _waterSampleContainer.top + topMargin : Variables.defaultMargin * 3 // with current resolution this makes the screen look nice + horizontalCenter: parent.horizontalCenter + } + } + + Text { id: _description + anchors.centerIn: parent + color : Colors.textMain + font.pixelSize : Fonts.fontPixelInstructionStep + font.weight : Font.Medium + } + + TouchRect { id : _button + width : Variables.confirmButtonWidth + height : Variables.contentHeight + text { + font.pixelSize : Fonts.fontPixelConfirm + font.weight : Font.Medium + } + + isDefault: true + + anchors { + horizontalCenter: _waterSampleContainer.horizontalCenter + bottom : _waterSampleContainer.bottom + bottomMargin : Variables.defaultMargin * 2 // with current resolution this makes the screen look nice + } + + onClicked: _waterSampleContainer.clicked() + } + } + + Row { id: _row + anchors { + top : _root.title.bottom + topMargin : Variables.defaultMargin * 4 // with current resolution this makes the screen look nice + horizontalCenter: parent.horizontalCenter + } + + spacing : Variables.defaultMargin * 2 // with current resolution this makes the screen look nice + + WaterSampleContainer { id: _failContainer + imageSource : "qrc:/images/iWaterSampleFail" + buttonText : qsTr("Fail") + description : qsTr("Chlorine level > 0.1 %1").arg(Variables.unitTextChlorine) + onClicked :{ + _failContainer.selected = true + _passContainer.selected = false + } + } + + WaterSampleContainer { id: _passContainer + imageSource : "qrc:/images/iWaterSamplePass" + buttonText : qsTr("Pass") + description : qsTr("Chlorine level ≤ 0.1 %1").arg(Variables.unitTextChlorine) + onClicked :{ + _failContainer.selected = false + _passContainer.selected = true + } + } + } +} Fisheye: Tag 4a2b83dcb56555861d2c741a8e8894e5b07e24bf refers to a dead (removed) revision in file `sources/gui/qml/pages/pretreatment/PreTreatmentWaterSampleStack.qml'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4a2b83dcb56555861d2c741a8e8894e5b07e24bf refers to a dead (removed) revision in file `sources/gui/qml/pages/pretreatment/connection/PreTreatmentConnectionStack.qml'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4a2b83dcb56555861d2c741a8e8894e5b07e24bf refers to a dead (removed) revision in file `sources/gui/qml/pages/pretreatment/connection/PreTreatmentUltrafiltration.qml'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/view/settings/VSettings.cpp.autosave =================================================================== diff -u --- sources/view/settings/VSettings.cpp.autosave (revision 0) +++ sources/view/settings/VSettings.cpp.autosave (revision 4a2b83dcb56555861d2c741a8e8894e5b07e24bf) @@ -0,0 +1,369 @@ +/*! + * + * Copyright (c) 2021-2024 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 VSettings.cpp + * \author (last) Behrouz NematiPour + * \date (last) 10-Jul-2024 + * \author (original) Behrouz NematiPour + * \date (original) 29-Mar-2021 + * + */ +#include "VSettings.h" + +// Qt +#include +#include + +// Project +#include "GuiController.h" +#include "MSettings.h" +#include "Settings.h" +#include + +VIEW_DEF_CLASS(VSettings) + +void VSettings::initConnections() { + ACTION_VIEW_CONNECTION (SettingsData ); + connect(&_GuiController, SIGNAL(didActionReceive (GuiActionType, const QVariantList &)), + this , SLOT( onActionReceive (GuiActionType, const QVariantList &))); + +} + +void VSettings::initConnectionsSettings() +{ + static bool init = false; if ( init ) return; + + PROPERTY_POST_CONNECTION(VSettings, servicePass ); + PROPERTY_POST_CONNECTION(VSettings, alarmVolume ); + PROPERTY_POST_CONNECTION(VSettings, roWaterMode ); + PROPERTY_POST_CONNECTION(VSettings, advancedMode); + + init = true; +} + +void VSettings::servicePass_post(const QString &vservicePass) { + //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. + if ( Storage::Settings::save(servicePass(), servicePassKey(), vservicePass) != 0 ) { + servicePass(""); + // FIXME: Notify UI with a message + } +} + +void VSettings::roWaterMode_post(const bool &vroWaterMode_post) { + //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. + if ( Storage::Settings::save(roWaterMode(), roWaterModeKey(), QString::number(vroWaterMode_post)) != 0 ) { + roWaterMode(false); + // FIXME: Notify UI with a message + } +} + +void VSettings::advancedMode_post(const bool &vadvancedMode_post) { + //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. + if ( Storage::Settings::save(advancedModeGroup(), advancedModeKey(), QString::number(vadvancedMode_post)) != 0 ) { + advancedMode(false); + // FIXME: Notify UI with a message + } +} + +void VSettings::alarmVolume_post(const quint8 &valarmVolume) { + //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. + Storage::Settings::save(alarmVolumeGroup(), alarmVolumeKey(), QString::number(valarmVolume)); +} + +void VSettings::onActionReceive(const SettingsData &) +{ + // TODO: this function needs to be moved to the controller, to execute in settings thread not the main thread. + // it should then send the output here to update the specific properties defined. + QStringList mCategorys = _Settings.categorys(); + for (const auto &category : mCategorys) { + QStringList groups = _Settings.groups(category); + for (const auto &group : groups) { + QStringList keys ; + QVariantList values ; + QString title = ""; + for (const QString &key : _Settings.keys(category, group)) { + if (Storage::Settings::isKeyTitle ( key ) ) { + title = _Settings.value(category, group, key).toString(); + } else { + const QString imagePath = QStringLiteral("%1%2").arg(_location) + .arg(_Settings.value(category, group, key).toString()); + QFileInfo fileInfo(imagePath); + values.append(fileInfo.exists() && fileInfo.isFile() ? "file:" + imagePath : ""); + keys.append(key); + } + } + + if ( Storage::Settings::isCategoryInstructions( category ) ) { + TKeysList keysList = updateReplacements(group, keys ); + updateInstructions(group, keysList, values, title ); + updateInstructions(group ); + + + } + else { //TODO: Since it is global system settings, move this to the settings controller so the C++ backend can also use it. like Date/Time formats. + for (const auto &key : qAsConst(keys)) { + // DEBUG: qDebug() << " ~~~~~~~~~~ " << category << group << key << _Settings.value(category, group, key).toString (); + QVariantMap keyValue; + if ( isservicePass (category, group, key) ) { + QString mServicePass; + mServicePass = _Settings.value(category, group, key).toString (); + keyValue[key] = mServicePass ; + servicePass ( mServicePass); + } + else if ( isroWaterMode (category, group, key) ) { + bool mRoWaterMode; + mRoWaterMode = _Settings.value(category, group, key).toBool (); + keyValue[key] = mRoWaterMode ; + roWaterMode ( mRoWaterMode); + } + else if ( isadvancedMode(category, group, key) ) { + bool mAdvancedMode; + mAdvancedMode = _Settings.value(category, group, key).toBool (); + keyValue[key] = mAdvancedMode ; + advancedMode ( mAdvancedMode ); + } + else if ( isalarmVolume (category, group, key) ) { + quint8 mAlarmVolume; + mAlarmVolume = _Settings.value(category, group, key).toInt (); // returns 0 if fails, so no error checking needed. + keyValue[key] = mAlarmVolume ; + alarmVolume ( mAlarmVolume); + } + else { + keyValue[key] = _Settings.value(category, group, key); + } + } + } + } + } + + categorys (mCategorys); + emit instructionsChanged(_instructions); + + // If the configuration exits, then it has been set, and this call internally will be neutral, + // otherwise will use the default value and will notify the update. + servicePass ( _servicePass ); + alarmVolume ( _alarmVolume ); + roWaterMode ( _roWaterMode ); + advancedMode( _advancedMode ); + + //DEBUG qDebug() << servicePass() << roWaterMode() << alarmVolume(); + adjustment(true); + + initConnectionsSettings(); +} + +VSettings::TKeysList VSettings::updateReplacements(const QString &vGroup, const QStringList &vKeys) +{ + TKeysList keysList; + for ( quint16 keyIndex = 0; keyIndex < vKeys.count(); keyIndex++ ) { + QRegExp regx("\\{\\s*\\d+\\s*:\\s*\\d+\\s*:\\s*\\w*\\s*:\\s*\\d*\\s*\\}"); + QString key = vKeys[keyIndex]; + int replacementCount = key.count(regx); + QStringList keyList; + for ( int j = 0; j < replacementCount; j++ ) { + int pos = key.indexOf(regx); + int len = regx.matchedLength(); + QString blk = key.mid(pos+1, len-2); + keyList += key.mid(0, pos); + keyList += ""; // value placeholder + key.remove(0, pos + regx.matchedLength()); + QStringList lst = blk.split(":"); + quint16 id = lst[0].toUInt(); + quint16 ix = lst[1].toUInt(); + QString ex = lst[2] ; + quint16 rd = lst[3].toUInt(); + TLocation loc; + loc.group = vGroup ; + loc.keyIndex = keyIndex ; + loc.locIndex = j * 2 + 1 ; + loc.prmIndex = ix ; + loc.prmExtra = ex ; + loc.prmRound = rd ; + _replacements[id] += loc; + //DEBUG: qDebug() << "#" << replacementCount << id << loc.group << loc.keyIndex << loc.locIndex << loc.prmIndex; + } + keyList += key; + keysList += keyList; + } + return keysList; +} + +void VSettings::updateInstructions(const QString &vGroup, const TKeysList &vKeysList, const QVariantList &vValues, const QString &vTitle) +{ + TInstruction mInstruction; + mInstruction.title = vTitle; + mInstruction.keys = vKeysList; + mInstruction.values = vValues ; + _instructionMap[vGroup] = mInstruction; +} + +void VSettings::updateInstructions(const QString &vGroup) +{ + //TODO: this function or even the structure may need to update to send less data to qml and only the updated part. + TKeysList keysList = _instructionMap[vGroup].keys ; + QVariantList values = _instructionMap[vGroup].values; + QString title = _instructionMap[vGroup].title; + QStringList keyList; + for ( const auto &keys : keysList) { + keyList += keys.join(""); + } + QVariantMap details; + details["title"] = title ; + details["keys" ] = keyList ; + details["values" ] = values ; + _instructions[vGroup] = details ; +} + +/*! + * \brief VSettings::onActionReceive + * \details emits didActionReceive signal to notify other classes (Gui) + * , an action has been received. + * \param vAction - the action + * \param vData - the action data + */ +void VSettings::onActionReceive (GuiActionType vAction, const QVariantList &vData) +{ + bool isChanged = false; + quint16 id = qFromBigEndian((quint16)vAction); + if (_replacements.contains(id)) { + isChanged = true; + //DEBUG: qDebug() << _replacements[id].count(); + for ( const auto &item : _replacements[id]) { + //DEBUG: qDebug() << id << item.group << item.keyIndex << item.locIndex << item.prmIndex; + QString value; + quint16 len = vData.length(); + if ( 0 < item.prmIndex && item.prmIndex <= len ) { + if ( item.prmRound > 0 ) { + value = QString::number(vData[item.prmIndex - 1].toFloat(), 'f', item.prmRound) + item.prmExtra; + } + else { + value = vData[item.prmIndex - 1].toString() + item.prmExtra; + } + } + else { + LOG_DEBUG(QString("Given prmIndex %1 is out of message %2 parameters count %3 on instruction group '%4' and key index %5") + .arg(item.prmIndex).arg(id).arg(len).arg(item.group).arg(item.keyIndex)); + continue; + } + _instructionMap[item.group].keys[item.keyIndex][item.locIndex] = value; + updateInstructions(item.group); + } + } + if ( isChanged ) emit instructionsChanged(_instructions); +} + +/*! + * \brief Return whether the password has the minimum character limit + * \param[in] password password to check + * \return true if the password contains requirement + */ +bool View::VSettings::passwordContainsCharacterLimit(const QString &vPassword) const +{ + return vPassword.size() >= 10; +} + +/*! + * \brief Return whether the password has a upper case letter + * \param[in] password password to check + * \return true if the password contains requirement + */ +bool View::VSettings::passwordContainsUpperCase(const QString &vPassword) const +{ + static const QRegularExpression upperCaseLetter("[A-Z]"); + return vPassword.contains(upperCaseLetter); +} + +/*! + * \brief Return whether the password has a lower case letter + * \param[in] password password to check + * \return true if the password contains requirement + */ +bool View::VSettings::passwordContainsLowerCase(const QString &vPassword) const +{ + static const QRegularExpression lowerCaseLetter("[a-z]"); + return vPassword.contains(lowerCaseLetter); +} + +/*! + * \brief Return whether the password has a digit + * \param[in] password password to check + * \return true if the password contains requirement + */ +bool View::VSettings::passwordContainsDigit(const QString &vPassword) const +{ + static const QRegularExpression number("[0-9]"); + return vPassword.contains(number); +} + +bool View::VSettings::passwordContainsSymbol(const QString &vPassword) const +{ + static const QRegularExpression symbol( + QStringLiteral("[%1]").arg(QRegularExpression::escape("{}[],.<>;:'\"?/|\\`~!@#$%^&*()_-+="))); + return vPassword.contains(symbol); +} + +/*! + * \brief Return whether the password is high strength. + * \param[in] password password to check + * \return true if the password is high strength and false otherwise. + */ +bool View::VSettings::isPasswordHighStrength(const QString &vPassword) const +{ + return passwordContainsUpperCase(vPassword) && + passwordContainsLowerCase(vPassword) && + passwordContainsDigit(vPassword) && + passwordContainsSymbol(vPassword) && + passwordContainsCharacterLimit(vPassword); +} + +QString View::VSettings::hashedPassword(const QString &vPassword, bool vIsService) +{ + bool ok; + QString hashed = encryption::hashedString(vPassword, ok, ! vIsService); + encryptionPass(ok); + return ok ? hashed : ""; +} + +/*! + * \brief View::VSettings::isServicePasswordMatch + * \details matches the given password string, vPassword, with the service password. + * \param vPassword - the given password string + * \return true if it matches. + */ +bool View::VSettings::isServicePasswordMatch(const QString &vPassword) +{ + //DEBUG qDebug() << __FUNCTION__ << _servicePass << hashedPassword(vPassword, true); + bool isNotEmpty = ( ! vPassword.trimmed().isEmpty() ); + bool isMatch = ( _servicePass == hashedPassword(vPassword, true) ); + bool isValid = isMatch && isNotEmpty; + if ( isValid ) { + LOG_DEBUG("Valid Service Password Entered!"); + } + else { + LOG_DEBUG("Invalid Service Password Entered!"); + } + return isValid; +} + +/*! + * \brief View::VSettings::updateServicePassword + * \details Updatest the service password with the given password. + * \param vPassword - the password to be saved as the service password. + */ +void View::VSettings::updateServicePassword(const QString &vPassword) +{ + servicePass(hashedPassword(vPassword, true)); +} + +void View::VSettings::checkServicePasswordSet() +{ + bool ok; + isDefaultServicePassword(encryption::isDefaultServicePassword(servicePass(), ok)); + //DEBUG qDebug() << __FUNCTION__ << ok; + encryptionPass(ok); +} +