Index: denali.pro =================================================================== diff -u -rcbea4224ad67eecc2e7c4c66df9a7db711c72832 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- denali.pro (.../denali.pro) (revision cbea4224ad67eecc2e7c4c66df9a7db711c72832) +++ denali.pro (.../denali.pro) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -14,6 +14,15 @@ DEFINES += DISABLE_KEEP_ALIVE } +DEFINES += "\"QT_MESSAGE_PATTERN=[%{type}] (%{file}:%{line}) - %{message}\"" + +CONFIG(debug, debug | release ) { + DEFINES += DEBUG +} else { + DEFINES += RELEASE + DEFINES += QT_NO_DEBUG_OUTPUT +} + # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Refer to the documentation for the @@ -51,8 +60,11 @@ sources/model/mtreatmentadjustultrafiltrationconfirmresponse.h \ sources/model/mtreatmentadjustultrafiltrationstateresponse.h \ sources/model/mtreatmentadjustultrafiltrationeditresponse.h \ + sources/model/mtreatmentparameters.h \ + sources/model/mtreatmentparametersresp.h \ sources/model/mtreatmentpressureocclusion.h \ sources/model/mtreatmentranges.h \ + sources/storage/filesaver.h \ sources/threads.h \ sources/applicationcontroller.h \ sources/applicationpost.h \ @@ -74,6 +86,7 @@ sources/model/mtreatmentflows.h \ sources/model/mtreatmentoutletflow.h \ sources/model/mtreatmenttime.h \ + sources/view/VCreateTreatment.h \ sources/view/vloadcellreadings.h \ sources/view/vtemperaturesensors.h \ sources/view/vtreatmentadjustmentduration.h \ @@ -110,8 +123,11 @@ sources/model/mtreatmentadjustultrafiltrationconfirmresponse.cpp \ sources/model/mtreatmentadjustultrafiltrationstateresponse.cpp \ sources/model/mtreatmentadjustultrafiltrationeditresponse.cpp \ + sources/model/mtreatmentparameters.cpp \ + sources/model/mtreatmentparametersresp.cpp \ sources/model/mtreatmentpressureocclusion.cpp \ sources/model/mtreatmentranges.cpp \ + sources/storage/filesaver.cpp \ sources/threads.cpp \ sources/applicationcontroller.cpp \ sources/applicationpost.cpp \ @@ -131,6 +147,7 @@ sources/model/mtreatmentoutletflow.cpp \ sources/model/mtreatmenttime.cpp \ sources/model/malarmstatus.cpp \ + sources/view/VCreateTreatment.cpp \ sources/view/vloadcellreadings.cpp \ sources/view/vpoweroff.cpp \ sources/view/vtemperaturesensors.cpp \ Index: denali.pro.user =================================================================== diff -u -r305d411b4bc617d858075f5750dea487d707bebb -rc71deaab48699cffdf9db816dfac2778d79c2238 --- denali.pro.user (.../denali.pro.user) (revision 305d411b4bc617d858075f5750dea487d707bebb) +++ denali.pro.user (.../denali.pro.user) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -1,6 +1,6 @@ - + EnvironmentId @@ -68,7 +68,7 @@ Desktop Qt 5.12.5 GCC 64bit Desktop Qt 5.12.5 GCC 64bit qt.qt5.5125.gcc_64_kit - 1 + 0 0 0 @@ -1164,7 +1164,7 @@ false true - /home/denali/Project/tmp/build/denali-Desktop_Qt_5_12_5_GCC_64bit-Release + /home/denali/Project/tmp/build/denali-Desktop_Qt_5_12_5_GCC_64bit-Debug 1 Index: denali.qrc =================================================================== diff -u -rc8eb6d0e29f8951a793b2f52d11a08b9902470ee -rc71deaab48699cffdf9db816dfac2778d79c2238 --- denali.qrc (.../denali.qrc) (revision c8eb6d0e29f8951a793b2f52d11a08b9902470ee) +++ denali.qrc (.../denali.qrc) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -20,9 +20,9 @@ resources/images/ArrowRight.png resources/images/logo d Dark Transparent.png resources/images/Close.png - resources/images/alarm.svg - resources/images/bell.svg - resources/images/bell-off.svg + resources/images/alarm.png + resources/images/bell.png + resources/images/bell-off.png resources/images/Back.png resources/images/Pause.png resources/images/Resume.png @@ -55,10 +55,14 @@ sources/gui/qml/components/RangeRect.qml sources/gui/qml/components/RangeBar.qml sources/gui/qml/components/Circle.qml + sources/gui/qml/components/CircleWithText.qml sources/gui/qml/components/TimeText.qml sources/gui/qml/components/ProgressCircle.qml sources/gui/qml/components/Slider.qml sources/gui/qml/components/SliderCreateTreatment.qml + sources/gui/qml/components/SliderDoubleCreateTreatment.qml + sources/gui/qml/components/RectSelectCreateTreatment.qml + sources/gui/qml/components/TopMenuBarCreateTreatment.qml sources/gui/qml/components/ProgressBarEx.qml sources/gui/qml/components/CloseButton.qml sources/gui/qml/components/ConfirmButton.qml @@ -85,6 +89,9 @@ sources/gui/qml/pages/treatment/TreatmentHome.qml sources/gui/qml/pages/treatment/TreatmentStack.qml sources/gui/qml/pages/treatment/TreatmentCreate.qml + sources/gui/qml/pages/treatment/TreatmentBegin.qml + sources/gui/qml/pages/treatment/TreatmentConfirm.qml + sources/gui/qml/pages/treatment/TreatmentPrime.qml sources/gui/qml/pages/treatment/TreatmentStart.qml Index: resources/images/alarm.png =================================================================== diff -u Binary files differ Index: resources/images/bell-off.png =================================================================== diff -u Binary files differ Index: resources/images/bell.png =================================================================== diff -u Binary files differ Index: sources/applicationcontroller.cpp =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/applicationcontroller.cpp (.../applicationcontroller.cpp) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/applicationcontroller.cpp (.../applicationcontroller.cpp) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -15,6 +15,8 @@ #include "applicationcontroller.h" // Qt +#include +#include // Project #include "maintimer.h" @@ -24,6 +26,9 @@ #include "filehandler.h" #include "guicontroller.h" + +using namespace Storage; + /*! * \brief ApplicationController::ApplicationController * \details Constructor Index: sources/applicationcontroller.h =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/applicationcontroller.h (.../applicationcontroller.h) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/applicationcontroller.h (.../applicationcontroller.h) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -23,6 +23,7 @@ #include "applicationpost.h" #include "mmodel.h" #include "messageglobals.h" +#include "mtreatmentparameters.h" // define #define _ApplicationController ApplicationController::I() @@ -67,6 +68,8 @@ void createFakeSequencedLongMessage (QVariantList &vData, const int vFakeDataLen); void createFakeSeqAtBeginLongMessage(QVariantList &vData, const int vFakeDataLen); + void saveNewTreatment(QJsonObject obj); + private slots: // Should be private for thread safety and is connected internally. void onActionReceive (GuiActionType vAction, const QVariantList &vData); // UI <= HD/DG void onActionTransmit(GuiActionType vAction, const QVariantList &vData); // UI => HD/DG Index: sources/canbus/messageglobals.h =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/canbus/messageglobals.h (.../messageglobals.h) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/canbus/messageglobals.h (.../messageglobals.h) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -82,6 +82,10 @@ {Gui::GuiActionType::AdjustUltrafiltrationConfirmReq , 2 * 4 }, // 2 parameters each 4bytes {Gui::GuiActionType::AdjustUltrafiltrationConfirmRsp , 5 * 4 }, + // --- + {Gui::GuiActionType::CreateTreatmentReq , 17 * 4 }, // 17 parameters, each 4 bytes + {Gui::GuiActionType::CreateTreatmentRsp , 18 * 4 }, // 18 parameters, each 4 bytes + // ---- {Gui::GuiActionType::CanBUSFaultCount , 1 }, {Gui::GuiActionType::String , 255 }, Index: sources/canbus/messageinterpreter.cpp =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/canbus/messageinterpreter.cpp (.../messageinterpreter.cpp) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/canbus/messageinterpreter.cpp (.../messageinterpreter.cpp) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -290,6 +290,10 @@ ok = adjustUltrafiltrationConfirmData (vMessage, vData); break; + case Gui::GuiActionType::CreateTreatmentRsp: + ok = createTreatmentRespData (vMessage, vData); + break; + // unhandles messages: these will only be logged as received message // there has nothing been defined for these messages. case Gui::GuiActionType::AlarmTriggered: @@ -930,3 +934,26 @@ return ok; } + +/*! + * \brief MessageInterpreter::createTreatmentRespData + * Checks the validity of the create treatment response data. + * \param vMessage - The message + * \param vData - the output data + * \return true if ok, false otherwise + */ +bool MessageInterpreter::createTreatmentRespData(const Message &vMessage, QVariantList &vData) { + bool ok = false; + if ( ! isType (vMessage, Gui::GuiActionType::CreateTreatmentRsp) ) return ok; + if ( ! isPayloadLenValid(vMessage, Gui::GuiActionType::CreateTreatmentRsp) ) return ok; + + Model::TreatmentParametersResp mData; + ok = mData.fromByteArray(vMessage.data); + LOG_DATUM(mData.toString()); + + mData.toVariantList(vData); + emit didActionReceive(mData.data()); + + return ok; + +} Index: sources/canbus/messageinterpreter.h =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/canbus/messageinterpreter.h (.../messageinterpreter.h) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/canbus/messageinterpreter.h (.../messageinterpreter.h) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -106,6 +106,10 @@ // ---- Treatment Adjust response for Treatment Ultrafiltration state (Pause / Resume) change bool adjustUltrafiltrationStateData (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + + // ---- Create Treatment Response Data + bool createTreatmentRespData (const Message &vMessage, QVariantList &vData) __attribute_warn_unused_result__; + public: explicit MessageInterpreter(QObject *parent = nullptr); Index: sources/gui/guicontroller.cpp =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/guicontroller.cpp (.../guicontroller.cpp) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/gui/guicontroller.cpp (.../guicontroller.cpp) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -298,4 +298,3 @@ data.mFlags = QBitArray(16, false); // 16 QBitArray of flags, if needed emit didActionReceive(data); } - Index: sources/gui/guicontroller.h =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/guicontroller.h (.../guicontroller.h) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/gui/guicontroller.h (.../guicontroller.h) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -27,7 +27,6 @@ #define _GuiController GuiController::I() using namespace Can; - // namespace namespace Gui { Index: sources/gui/guiglobals.cpp =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/guiglobals.cpp (.../guiglobals.cpp) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/gui/guiglobals.cpp (.../guiglobals.cpp) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -43,6 +43,7 @@ #include "vtreatmentadjustmentflows.h" #include "vtreatmentadjustmentultrafiltrationedit.h" #include "vtreatmentadjustmentultrafiltrationconfirm.h" +#include "VCreateTreatment.h" namespace Gui { QQuickView *_viewer = nullptr; Index: sources/gui/guiglobals.h =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/guiglobals.h (.../guiglobals.h) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/gui/guiglobals.h (.../guiglobals.h) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -40,6 +40,8 @@ * *** then it can be compared exactly the way it is with no conversion.***\n */ enum GuiActionsType_Enum /*: quint16 QML doesn't support enum types */ { + // necessary to add CreateTreatment here? We're saving to filesystem, but what might we need to tell the HD + // when a new treatment is created? Unknown = 0x0000, PowerOff = 0x0100, @@ -54,8 +56,11 @@ AlarmTriggered = 0x0300, AlarmCleared = 0x0400, AlarmSilenceReq = 0x2F00, // 47 - Not implemented yet on FW side - AlarmSilenceRsp = 0x3000, // 48 - Not implemented yet on FW side + AlarmSilenceRsp = 0x3000, // 48 - TODO: As per conversation with Sean this can be deleted. + CreateTreatmentReq = 0x3500, // 53 - Not implemented yet on FW side + CreateTreatmentRsp = 0x3600, // 54 - Not implemented yet on FW side + LoadCellReadings = 0x0C00, PressureOcclusion = 0x0900, Index: sources/gui/qml/components/CircleWithText.qml =================================================================== diff -u --- sources/gui/qml/components/CircleWithText.qml (revision 0) +++ sources/gui/qml/components/CircleWithText.qml (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,68 @@ +/*! + * + * Copyright (c) 2019-2020 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 CircleWithText.qml + * \author (last) Peter Lucia + * \date (last) 16-Jul-2020 + * \author (original) Peter Lucia + * \date (original) 16-Jul-2020 + * + */ + +// Qt +import QtQuick 2.12 + +// Project + +// Qml imports +import "qrc:/globals" +import "qrc:/components" + +Rectangle { id: _root + property int diameter : 10 + property var text : "" + height: 35 + width: diameter + color: "transparent" + + Rectangle { id: _circle + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + height: _root.diameter + width: _root.diameter + radius: _root.diameter + color: Colors.backgroundRangeRect + } + + Text { id: _text + anchors.top: _circle.bottom + anchors.topMargin: 5 + anchors.horizontalCenter: _circle.horizontalCenter + text: _root.text + color: Colors.textMain + } + + states: [ + State { + name: "active" + PropertyChanges { target: _root; diameter: 15 } + PropertyChanges { target: _circle; color: Colors.createTreatmentActive } + PropertyChanges { target: _text; color: Colors.textMain } + + }, + State { + name: "inactive" + PropertyChanges { target: _root; diameter: 10 } + PropertyChanges { target: _circle; color: Colors.createTreatmentInactive } + PropertyChanges { target: _text; color: Colors.createTreatmentInactive } + + } + ] + +} + + Index: sources/gui/qml/components/NotificationBar.qml =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/qml/components/NotificationBar.qml (.../NotificationBar.qml) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/gui/qml/components/NotificationBar.qml (.../NotificationBar.qml) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -35,7 +35,7 @@ function toggleSilence(silence, timeoutSec) { isSilenced = silence; muteTimeoutSec = !isSilenced ? 0 : timeoutSec; - _bell.source = isSilenced ? "qrc:/images/bell-off.svg" : "qrc:/images/bell.svg" + _bell.source = isSilenced ? "qrc:/images/bell-off.png" : "qrc:/images/bell.png" } // Placeholder animation @@ -67,7 +67,7 @@ Image { id: _icon - source: "qrc:/images/alarm.svg" + source: "qrc:/images/alarm.png" anchors.right: _text.left anchors.rightMargin: Variables.notificationBarIconMargin; anchors.verticalCenter: parent.verticalCenter; @@ -86,7 +86,7 @@ Image { id: _bell - source: isSilenced ? "qrc:/images/bell-off.svg" : "qrc:/images/bell.svg" + source: isSilenced ? "qrc:/images/bell-off.png" : "qrc:/images/bell.png" anchors.left: _root.left anchors.leftMargin: Variables.silenceIconMargin; anchors.verticalCenter: parent.verticalCenter; Index: sources/gui/qml/components/RectSelectCreateTreatment.qml =================================================================== diff -u --- sources/gui/qml/components/RectSelectCreateTreatment.qml (revision 0) +++ sources/gui/qml/components/RectSelectCreateTreatment.qml (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,93 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright \n + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, \n + * IN PART OR IN WHOLE, \n + * WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. \n + * + * \file SliderCreateTreatment.qml + * \date 2020/07/07 + * \author Peter Lucia + * + */ + +// Qt +import QtQuick 2.12 +import QtQuick.Layouts 1.12 + + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" + +// TODO: if possible, make this a component +Rectangle { + id: _root + anchors.horizontalCenter: parent.horizontalCenter + color: "transparent" + property int numRows: 2 + property int numCols: 2 + property int buttonHeight: 78 + property int buttonWidth: 313 + property var buttonNames: ["Button 1", "Button 2", "Button 3"] + property alias name: _text.text + property int selectedIndex: unselectedIndex + property int unselectedIndex: 9999 + height: numRows * buttonHeight + width: numCols * buttonWidth + signal buttonClicked() + + Text { + id: _text + text: "Title" + font.pixelSize: Fonts.fontPixelFluidText + color: Colors.textMain; + } + function setActive(active) { + if (!active) { + for (let i = 0; i < _repeater.count; i++) { + _repeater.itemAt(i).setSelected(false) + } + selectedIndex = unselectedIndex + } + } + + GridLayout { + id: _grid + anchors.top: _text.bottom + anchors.topMargin: Variables.sliderTextMargin + rows: parent.numRows + columns: parent.numCols + + Repeater { id: _repeater + model: buttonNames + TouchRect { + id: _touchRect + text.text: modelData; + selectable: true + height: _root.buttonHeight + width: _root.buttonWidth + radius: 0 + onClicked: { + if (selectedIndex === index) { + _repeater.itemAt(index).setSelected(false) + selectedIndex = unselectedIndex + } else { + _repeater.itemAt(index).setSelected(true) + selectedIndex = index + } + + for (let j = 0; j < _repeater.count; j += 1) { + if (index !== j) { + _repeater.itemAt(j).setSelected(false) + } + } + buttonClicked() + } + } + } + } + +} Index: sources/gui/qml/components/Slider.qml =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/qml/components/Slider.qml (.../Slider.qml) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/gui/qml/components/Slider.qml (.../Slider.qml) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -36,7 +36,37 @@ property alias handler : _handler + property alias diameter : _handler.diameter + property alias knobColor : _handler.color + property bool isActive : false; + signal progressRectClicked() + signal progressRectDragged() + signal activeChanged() + + function setActive(active) { + if (active) { + color = Colors.createTreatmentActive + knobColor = Colors.createTreatmentActive + } else { + color = Colors.createTreatmentInactive + knobColor = Colors.createTreatmentInactive + } + + if (active !== isActive) { + isActive = active; + activeChanged() + } + } + + onIsActiveChanged: { + setActive(isActive) + if (!isActive) { + value = minimum + } + activeChanged() + } + height : Variables.progressbarHeight touchMargin : 25 @@ -76,7 +106,7 @@ value = getValueOfX(x) - if ( step === 1 ) { /* keep the value and return */ return; } + if ( step === 1 ) { value = parseInt(value); return; } var start = 0 if ( ! stepSnap ) start = minimum @@ -97,9 +127,11 @@ // propagation is not working on drag ! onDragged: { setValue(vMouseEvent.x) + progressRectDragged() } onClicked: { setValue(vMouseEvent.x) + progressRectClicked() } } Index: sources/gui/qml/components/SliderCreateTreatment.qml =================================================================== diff -u -rd6869b2442823e77476ace6df006d0d000ec9b7a -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/qml/components/SliderCreateTreatment.qml (.../SliderCreateTreatment.qml) (revision d6869b2442823e77476ace6df006d0d000ec9b7a) +++ sources/gui/qml/components/SliderCreateTreatment.qml (.../SliderCreateTreatment.qml) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -24,9 +24,17 @@ id: _root property alias text: _text.text - property alias units: _slider.unit + property var units: "" property alias min: _slider.minimum property alias max: _slider.maximum + property alias value: _slider.value + property alias diameter: _slider.diameter + property alias selectedValue: _selected_value + property alias step: _slider.step + property alias stepSnap: _slider.stepSnap + property alias sliderWidth: _slider.width + property alias isActive: _slider.isActive + signal sliderChanged() height: Variables.progressbarRectHeight width: Variables.progressbarRectWidth @@ -47,24 +55,40 @@ id: _selected_value anchors.top: parent.top anchors.right: parent.right - text: "" + text: "-- " + _root.units font.pixelSize: Fonts.fontPixelFluidUnit - color: Colors.textMain; + color: Colors.textDisableButton; } Slider { id : _slider anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom; width : Variables.progressbarSmallWidth + diameter: Variables.sliderCircleDiameter + color : Colors.createTreatmentInactive + knobColor: Colors.createTreatmentInactive height : 5 minimum : 100 maximum : 500 unit : qsTr("") step : Variables.bloodFlowResolution ticks : true onValueChanged: { - _selected_value.text = value + unit; + _selected_value.text = value + _root.units + sliderChanged() } + onActiveChanged: { + if (isActive) { + _selected_value.color = Colors.textMain + } else { + _selected_value.color = Colors.textDisableButton + } + } + + onProgressRectClicked: setActive(true) + onProgressRectDragged: setActive(true) + onDragged: setActive(true) + onClicked: setActive(true) } } Index: sources/gui/qml/components/SliderDoubleCreateTreatment.qml =================================================================== diff -u --- sources/gui/qml/components/SliderDoubleCreateTreatment.qml (revision 0) +++ sources/gui/qml/components/SliderDoubleCreateTreatment.qml (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,161 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright \n + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, \n + * IN PART OR IN WHOLE, \n + * WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. \n + * + * \file SliderCreateTreatment.qml + * \date 2020/07/07 + * \author Peter Lucia + * + */ + +// Qt +import QtQuick 2.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" + +Rectangle { + id: _root + + property alias lowTitle: _lowTitle.text + property var lowUnits: "" + property alias highTitle: _highTitle.text + property var highUnits: "" + property alias lowMin: _lowSlider.minimum + property alias lowMax: _lowSlider.maximum + property alias highMin: _highSlider.minimum + property alias highMax: _highSlider.maximum + property alias lowValue: _lowSlider.value + property alias highValue: _highSlider.value + property alias lowDiameter: _lowSlider.diameter + property alias highDiameter: _highSlider.diameter + property alias lowSelectedValue: _lowSelectedValue + property alias highSelectedValue: _highSelectedValue + property alias lowStep: _lowSlider.step + property alias highStep: _highSlider.step + property alias lowStepSnap: _lowSlider.stepSnap + property alias highStepSnap: _highSlider.stepSnap + property alias lowSliderWidth: _lowSlider.width + property alias highSliderWidth: _highSlider.width + property alias isLowActive: _lowSlider.isActive + property alias isHighActive: _highSlider.isActive + signal lowSliderChanged() + signal highSliderChanged() + + height: Variables.progressbarRectHeight + width: Variables.progressbarSmallWidth + anchors.horizontalCenter: parent.horizontalCenter + color: "transparent"; + + Text { + id: _lowTitle + text: "Low" + anchors.top: parent.top + anchors.left: parent.left + font.pixelSize: Fonts.fontPixelFluidText + color: Colors.textMain; + + } + + Text { + id: _lowSelectedValue + anchors.top: parent.top + anchors.right: parent.horizontalCenter + anchors.rightMargin: Variables.progressbarSmallWidth / 15 + text: "-- " + _lowSlider.unit + font.pixelSize: Fonts.fontPixelFluidUnit + color: Colors.createTreatmentInactive; + + } + + Slider { id : _lowSlider + anchors.left: parent.left; + anchors.bottom: parent.bottom + width: Variables.progressbarSmallWidth / 2.3 + diameter: Variables.sliderCircleDiameter + color : Colors.createTreatmentInactive + knobColor: Colors.createTreatmentInactive + height : 5 + minimum: 0 + maximum: 100 + unit : qsTr("") + step : Variables.bloodFlowResolution + ticks : true + onValueChanged: { + _lowSelectedValue.text = value + _root.lowUnits; + lowSliderChanged() + } + onActiveChanged: { + if (isActive) { + _lowSelectedValue.color = Colors.textMain + } else { + _lowSelectedValue.color = Colors.createTreatmentInactive; + + } + } + + onProgressRectClicked: setActive(true) + onProgressRectDragged: setActive(true) + onDragged: setActive(true) + onClicked: setActive(true) + } + + Text { + id: _highTitle + text: "High" + anchors.top: parent.top + anchors.left: _highSlider.left + font.pixelSize: Fonts.fontPixelFluidText + color: Colors.textMain; + + } + + Text { + id: _highSelectedValue + anchors.top: parent.top + anchors.right: parent.right + text: "-- " + _highSlider.unit + font.pixelSize: Fonts.fontPixelFluidUnit + color: Colors.createTreatmentInactive; + + } + + Slider { id : _highSlider + anchors.right: parent.right; + anchors.bottom: parent.bottom; + width: Variables.progressbarSmallWidth / 2.3 + diameter: Variables.sliderCircleDiameter + color : Colors.createTreatmentInactive + knobColor: Colors.createTreatmentInactive + height : 5 + minimum: 50 + maximum: 100 + unit : qsTr("") + step : Variables.bloodFlowResolution + ticks : true + onValueChanged: { + _highSelectedValue.text = value + _root.highUnits; + highSliderChanged() + } + + onActiveChanged: { + if (isActive) { + _highSelectedValue.color = Colors.textMain + } else { + _highSelectedValue.color = Colors.createTreatmentInactive + + } + } + + onProgressRectClicked: setActive(true) + onProgressRectDragged: setActive(true) + onDragged: setActive(true) + onClicked: setActive(true) + } +} Index: sources/gui/qml/components/TopMenuBarCreateTreatment.qml =================================================================== diff -u --- sources/gui/qml/components/TopMenuBarCreateTreatment.qml (revision 0) +++ sources/gui/qml/components/TopMenuBarCreateTreatment.qml (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,129 @@ +/*! + * + * Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. + * \copyright \n + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, \n + * IN PART OR IN WHOLE, \n + * WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. \n + * + * \file SliderCreateTreatment.qml + * \date 2020/07/07 + * \author Peter Lucia + * + */ + +// Qt +import QtQuick 2.12 +import QtQuick.Layouts 1.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" + +Rectangle { id: _root + height: Variables.topBarMenuHeight + color: Colors.backgroundMainMenu + property var step: "CREATE"; + property int spacing: 5 + signal clickedBack() + + BackButton { id : _backButton + width: parent.width / 10 + anchors.verticalCenter: parent.verticalCenter + anchors.top: parent.top + anchors.left: parent.left + anchors.margins: _root.height / 4 + onClicked: clickedBack() + } + + Rectangle { + color: "transparent" + height: parent.height + width: parent.width + + anchors { + verticalCenter: parent.verticalCenter + horizontalCenter: parent.horizontalCenter + + } + + + RowLayout { + anchors.centerIn: parent + Layout.alignment: Qt.AlignVCenter + spacing: 5 + + CircleWithText { id: _create + text: "CREATE" + state: "active" + } + + Line { + length: 100 + color: Colors.createTreatmentInactive + } + + CircleWithText { id: _confirm + text: "CONFIRM" + } + + Line { + length: 100 + color: Colors.createTreatmentInactive + } + + CircleWithText { id: _prime + text: "PRIME" + + } + + Line { + id: _prime_line + length: 100 + color: Colors.createTreatmentInactive + } + + CircleWithText { id: _begin + text: "BEGIN" + } + + + } + } + + states: [ + State { + name: "create" + PropertyChanges { target: _create; state: "active" } + PropertyChanges { target: _confirm; state: "inactive" } + PropertyChanges { target: _prime; state: "inactive" } + PropertyChanges { target: _begin; state: "inactive" } + }, + State { + name: "confirm" + PropertyChanges { target: _create; state: "inactive" } + PropertyChanges { target: _confirm; state: "active" } + PropertyChanges { target: _prime; state: "inactive" } + PropertyChanges { target: _begin; state: "inactive" } + }, + State { + name: "prime" + PropertyChanges { target: _create; state: "inactive" } + PropertyChanges { target: _confirm; state: "inactive" } + PropertyChanges { target: _prime; state: "active" } + PropertyChanges { target: _begin; state: "inactive" } + }, + State { + name: "begin" + PropertyChanges { target: _create; state: "inactive" } + PropertyChanges { target: _confirm; state: "inactive" } + PropertyChanges { target: _prime; state: "inactive" } + PropertyChanges { target: _begin; state: "active" } + } + + ] + + + +} Index: sources/gui/qml/dialogs/NotificationDialog.qml =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/qml/dialogs/NotificationDialog.qml (.../NotificationDialog.qml) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/gui/qml/dialogs/NotificationDialog.qml (.../NotificationDialog.qml) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -62,7 +62,7 @@ Image { id: _icon - source: "qrc:/images/alarm.svg" + source: "qrc:/images/alarm.png" anchors.horizontalCenter: _title.horizontalCenter anchors.verticalCenter: _title.verticalCenter; anchors.horizontalCenterOffset: -_title.width + Variables.dialogSVGIconOffset; Index: sources/gui/qml/globals/Colors.qml =================================================================== diff -u -r305d411b4bc617d858075f5750dea487d707bebb -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/qml/globals/Colors.qml (.../Colors.qml) (revision 305d411b4bc617d858075f5750dea487d707bebb) +++ sources/gui/qml/globals/Colors.qml (.../Colors.qml) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -93,4 +93,12 @@ readonly property color alarmTopBarLowBg : "#db8f00" readonly property color alarmTopBarLowFg : "white" + readonly property color createTreatmentActive : "#3d8eef" + readonly property color createTreatmentInactive : "#3e546e" + readonly property color createTreatmentNotReady : "#1f4974" + readonly property color createTreatmentReady : "#438FEB" + readonly property color createTrTextNotReady : "#507090" + readonly property color createTrTextReady : "white" + + } Index: sources/gui/qml/globals/Variables.qml =================================================================== diff -u -r305d411b4bc617d858075f5750dea487d707bebb -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/qml/globals/Variables.qml (.../Variables.qml) (revision 305d411b4bc617d858075f5750dea487d707bebb) +++ sources/gui/qml/globals/Variables.qml (.../Variables.qml) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -84,7 +84,10 @@ readonly property int backIconDiameter : 17 readonly property int pauseIconDiameter : 60 + readonly property int topBarMenuHeight : 100 + readonly property int sliderCircleDiameter : 25 + // --- PRS --- readonly property int bloodFlowMin : 100 readonly property int bloodFlowMax : 500 Index: sources/gui/qml/main.qml =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/qml/main.qml (.../main.qml) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/gui/qml/main.qml (.../main.qml) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -39,6 +39,7 @@ import VLoadCellReadings 0.1; import VTemperatureSensors 0.1; +import VCreateTreatment 0.1; // Qml imports import "qrc:/globals" @@ -109,6 +110,7 @@ VTreatmentAdjustmentUltrafiltrationState { id: vTreatmentAdjustmentUltrafiltrationState } VTreatmentAdjustmentUltrafiltrationEdit { id: vTreatmentAdjustmentUltrafiltrationEdit } VTreatmentAdjustmentUltrafiltrationConfirm { id: vTreatmentAdjustmentUltrafiltrationConfirm } + VCreateTreatment { id: vCreateTreatment } // ----- Follow the below Z order ----- // 1 - Screens Index: sources/gui/qml/pages/treatment/TreatmentBegin.qml =================================================================== diff -u --- sources/gui/qml/pages/treatment/TreatmentBegin.qml (revision 0) +++ sources/gui/qml/pages/treatment/TreatmentBegin.qml (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,119 @@ +/*! + * + * Copyright (c) 2020 Diality Inc. - All Rights Reserved. + * \copyright \n + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, \n + * IN PART OR IN WHOLE, \n + * WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. \n + * + * \file TreatmentCreate.qml + * \author (last) Peter Lucia + * \date (last) 17-07-2020 + * \author (original) Behrouz NematiPour + * \date (original) 27-Jan-2020 + * + */ + +// Qt +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" + +/*! + * \brief ManagerHome is the screen + * which is the default screen in the "Manager" stack + */ +ScreenItem { id: _root + signal clickedBack() + signal clickedStart() + backgroundRect.color: Colors.backgroundMainMenu + + TopMenuBarCreateTreatment { id: _topMenuBar + anchors.top: parent.top + anchors.left: parent.left + width: parent.width + onClickedBack: { + _root.clickedBack(); + + } + state: "begin" + } + + + Flickable { + id: _flickable + anchors.top: _topMenuBar.bottom + anchors.left: parent.left + anchors.bottom: parent.bottom + width: parent.width + contentWidth: parent.width + contentHeight: _column.implicitHeight + clip: true + + Column { + id: _column + spacing: Variables.cTreatmentSpacing + anchors.horizontalCenter: parent.horizontalCenter; + anchors.fill: parent; + + Text { id: _titleText + anchors.horizontalCenter: parent.horizontalCenter; + text: qsTr("Begin Treatment") + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + } + + TouchRect { id : _continueRect + anchors.horizontalCenter: parent.horizontalCenter + text.text: qsTr("START") + button.onClicked: { + _root.clickedStart() + } + } + } + } + + states: [ + State { + when: _flickable.movingVertically + PropertyChanges { + target: _verticalScrollBar + opacity: 0.8 + } + } + ] + + ScrollBar { + anchors.top: _flickable.top + anchors.bottom: _flickable.bottom + id: _verticalScrollBar + size: _flickable.height / _column.implicitHeight + active: true + anchors.right: _flickable.right + anchors.rightMargin: 5 + opacity: 0 + orientation: Qt.Vertical + position: _flickable.visibleArea.yPosition + + contentItem: Rectangle { + color: Colors.backgroundRangeRect + implicitWidth: 6 + radius: width / 2 + width: 3 + } + + } + + onVisibleChanged: { + if (visible) { + _mainMenu.hidden = true + } + } + + +} Index: sources/gui/qml/pages/treatment/TreatmentConfirm.qml =================================================================== diff -u --- sources/gui/qml/pages/treatment/TreatmentConfirm.qml (revision 0) +++ sources/gui/qml/pages/treatment/TreatmentConfirm.qml (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,118 @@ +/*! + * + * Copyright (c) 2020 Diality Inc. - All Rights Reserved. + * \copyright \n + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, \n + * IN PART OR IN WHOLE, \n + * WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. \n + * + * \file TreatmentConfirm.qml + * \author (last) Peter Lucia + * \date (last) 17-07-2020 + * \author (original) Peter Lucia + * \date (original) 17-07-2020 + * + */ + +// Qt +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" + +/*! + * \brief ManagerHome is the screen + * which is the default screen in the "Manager" stack + */ +ScreenItem { id: _root + signal clickedBack() + signal clickedConfirm() + backgroundRect.color: Colors.backgroundMainMenu + + TopMenuBarCreateTreatment { id: _topMenuBar + anchors.top: parent.top + anchors.left: parent.left + width: parent.width + onClickedBack: { + _root.clickedBack(); + } + state: "confirm" + } + + + Flickable { + id: _flickable + anchors.top: _topMenuBar.bottom + anchors.left: parent.left + anchors.bottom: parent.bottom + width: parent.width + contentWidth: parent.width + contentHeight: _column.implicitHeight + clip: true + + Column { + id: _column + spacing: Variables.cTreatmentSpacing + anchors.horizontalCenter: parent.horizontalCenter; + anchors.fill: parent; + + Text { id: _titleText + anchors.horizontalCenter: parent.horizontalCenter; + text: qsTr("Confirm Treatment") + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + } + + TouchRect { id : _continueRect + anchors.horizontalCenter: parent.horizontalCenter + text.text: qsTr("CONFIRM TREATMENT") + button.onClicked: { + _root.clickedConfirm() + } + } + } + } + + states: [ + State { + when: _flickable.movingVertically + PropertyChanges { + target: _verticalScrollBar + opacity: 0.8 + } + } + ] + + ScrollBar { + anchors.top: _flickable.top + anchors.bottom: _flickable.bottom + id: _verticalScrollBar + size: _flickable.height / _column.implicitHeight + active: true + anchors.right: _flickable.right + anchors.rightMargin: 5 + opacity: 0 + orientation: Qt.Vertical + position: _flickable.visibleArea.yPosition + + contentItem: Rectangle { + color: Colors.backgroundRangeRect + implicitWidth: 6 + radius: width / 2 + width: 3 + } + + } + + onVisibleChanged: { + if (visible) { + _mainMenu.hidden = true + } + } + + +} Index: sources/gui/qml/pages/treatment/TreatmentCreate.qml =================================================================== diff -u -r305d411b4bc617d858075f5750dea487d707bebb -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/qml/pages/treatment/TreatmentCreate.qml (.../TreatmentCreate.qml) (revision 305d411b4bc617d858075f5750dea487d707bebb) +++ sources/gui/qml/pages/treatment/TreatmentCreate.qml (.../TreatmentCreate.qml) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -1,5 +1,4 @@ /*! -<<<<<<< HEAD * * Copyright (c) 2020 Diality Inc. - All Rights Reserved. * \copyright \n @@ -8,29 +7,16 @@ * WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. \n * * \file TreatmentCreate.qml - * \date 2020/07/07 - * \author Peter Lucia - * -======= - * - * Copyright (c) 2019-2020 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 TreatmentCreate.qml - * \author (last) Behrouz NematiPour - * \date (last) 12-May-2020 + * \author (last) Peter Lucia + * \date (last) 17-07-2020 * \author (original) Behrouz NematiPour * \date (original) 27-Jan-2020 - * ->>>>>>> master + * */ // Qt import QtQuick 2.12 import QtQuick.Controls 2.12 -import QtQuick.Layouts 1.12 // Project // Qml imports @@ -44,23 +30,19 @@ ScreenItem { id: _root signal clickedBack() signal clickedContinue() + backgroundRect.color: Colors.backgroundMainMenu - Rectangle { id: _topMenuBar + TopMenuBarCreateTreatment { id: _topMenuBar anchors.top: parent.top anchors.left: parent.left - height: Variables.mainMenuHeight; - width: parent.width; - color: Colors.backgroundMainMenu + width: parent.width + onClickedBack: { + _root.clickedBack(); - BackButton { id : _backButton - anchors.verticalCenter: parent.verticalCenter - anchors.top: parent.top - anchors.left: parent.left - anchors.margins: _topMenuBar.height / 6 - onClicked: clickedBack() } } + Flickable { id: _flickable anchors.top: _topMenuBar.bottom @@ -97,127 +79,239 @@ id: _bloodFlowRate text: "Blood Flow Rate" units: qsTr(" mL/min") - min: 100 - max: 500 + min: vCreateTreatment.bloodFlowRateMin + max: vCreateTreatment.bloodFlowRateMax + value: vCreateTreatment.bloodFlowRate + onSliderChanged: { + vCreateTreatment.bloodFlowRate = value; + } } SliderCreateTreatment { id: _dialysateFlowRate text: "Dialysate Flow Rate" units: qsTr(" mL/min") - min: 100 - max: 600 + min: vCreateTreatment.dialysateFlowRateMin + max: vCreateTreatment.dialysateFlowRateMax + onSliderChanged: { + vCreateTreatment.dialysateFlowRate = value; + } } SliderCreateTreatment { id: _duration text: "Duration" units: qsTr(" min") - min: 60 - max: 480 + min: vCreateTreatment.durationMin + max: vCreateTreatment.durationMax + onSliderChanged: { + vCreateTreatment.duration = value; + } } SliderCreateTreatment { id: _heparinDispensingRate text: "Heparin Dispensing Rate" - units: qsTr(" IU/hr") - min: 0 - max: 1000 + units: qsTr(" mL/hr") + min: vCreateTreatment.heparinDispensingRateMin + max: vCreateTreatment.heparinDispensingRateMax + onSliderChanged: { + vCreateTreatment.heparinDispensingRate = value; + } } SliderCreateTreatment { id: _heparinBolusVolume text: "Heparin Bolus Volume" - units: qsTr(" IU") - min: 100 - max: 2000 + units: qsTr(" mL") + min: vCreateTreatment.heparinBolusVolumeMin + max: vCreateTreatment.heparinBolusVolumeMax + onSliderChanged: { + vCreateTreatment.heparinBolusVolume = value; + } } - // TODO: if possible, make this a component - Rectangle { - id: _rectInfusionSolBolus - anchors.horizontalCenter: parent.horizontalCenter - color: "transparent" - property int numRows: 1 - property int numCols: 3 - property int buttonHeight: 96 - property int buttonWidth: 214 - height: numRows * buttonHeight - width: numCols * buttonWidth + SliderCreateTreatment { + id: _heparinStopTime + text: "Heparin Stop Time" + units: qsTr(" min") + min: vCreateTreatment.heparinStopTimeMin + max: vCreateTreatment.heparinStopTimeMax + onSliderChanged: { + vCreateTreatment.heparinStopTime = value; + } + } - Text { - id: _infusionSolutionBolus - text: "Infusion Solution Bolus" - font.pixelSize: Fonts.fontPixelFluidText - color: Colors.textMain; + RectSelectCreateTreatment { + id: _salineBolus + name: "Saline Bolus" + buttonNames: vCreateTreatment.salineBolusOptions + onButtonClicked: { + vCreateTreatment.salineBolusVolume = selectedIndex; } + } - GridLayout { - id: _grid - anchors.top: _infusionSolutionBolus.bottom - anchors.topMargin: Variables.sliderTextMargin - rows: parent.numRows - columns: parent.numCols + RectSelectCreateTreatment { + id: _acidConcentrate + name: "Acid Concentrate" + buttonNames: vCreateTreatment.acidConcentrateOptions; + onButtonClicked: { + vCreateTreatment.acidConcentrate = selectedIndex; + } + } - TouchRect { - id: _100mL - text.text: "100 mL"; - selectable: true - height: _rectInfusionSolBolus.buttonHeight - width: _rectInfusionSolBolus.buttonWidth - radius: 0 - onClicked: { - _200mL.setSelected(false) - _300mL.setSelected(false) - } - } + RectSelectCreateTreatment { + id: _bicarbonateConcentrate + name: "Bicarbonate Concentrate" + numRows: 1 + numCols: 2 + buttonNames: vCreateTreatment.bicarbonateConcentrateOptions; + onButtonClicked: { + vCreateTreatment.bicarbonateConcentrate = selectedIndex; + } + } - TouchRect { - id: _200mL - text.text: "200 mL"; - selectable: true - height: _rectInfusionSolBolus.buttonHeight - width: _rectInfusionSolBolus.buttonWidth - radius: 0 - onClicked: { - _300mL.setSelected(false) - _100mL.setSelected(false) - } - } + RectSelectCreateTreatment { + id: _dialyserType + name: "Dialyzer Type" + numRows: 3 + numCols: 2 + buttonNames: vCreateTreatment.dialyzerTypeOptions; + onButtonClicked: { + vCreateTreatment.dialyzerType = selectedIndex; + } + } - TouchRect { - id: _300mL - text.text: "300 mL"; - selectable: true - height: _rectInfusionSolBolus.buttonHeight - width: _rectInfusionSolBolus.buttonWidth - radius: 0 - animated: true - duration: 50 - onClicked: { - _100mL.setSelected(false) - _200mL.setSelected(false) - } - } + SliderCreateTreatment { + id: _dialysateTemperature + text: "Dialysate Temperature" + units: qsTr(" C") + step: 0.1 + min: vCreateTreatment.dialysateTempMin + max: vCreateTreatment.dialysateTempMax + onSliderChanged: { + vCreateTreatment.dialysateTemp = value; } + } + Text { + id: _arterialPressureLimitsTitle + text: "Arterial Pressure Limits" + anchors.left: _arterialPressureLimits.left + font.pixelSize: Fonts.fontPixelFluidText + color: Colors.textMain; + } + SliderDoubleCreateTreatment { + id: _arterialPressureLimits + lowTitle: "Low" + lowUnits: " mmHg" + highTitle: "High" + highUnits: " mmHg" + lowMin: vCreateTreatment.arterialPressureLimitLowMin + lowMax: vCreateTreatment.arterialPressureLimitLowMax + highMin: vCreateTreatment.arterialPressureLimitHighMin + highMax: vCreateTreatment.arterialPressureLimitHighMax + onLowSliderChanged: { + vCreateTreatment.arterialPressureLimitLow = lowValue + } + onHighSliderChanged: { + vCreateTreatment.arterialPressureLimitHigh = highValue + } + } + + + Text { + id: _venousPressureLimitsTitle + text: "Venous Pressure Limits" + anchors.left: _venousPressureLimits.left + font.pixelSize: Fonts.fontPixelFluidText + color: Colors.textMain; + + } + + SliderDoubleCreateTreatment { + id: _venousPressureLimits + lowTitle: "Low" + lowUnits: " mmHg" + highTitle: "High" + highUnits: " mmHg" + lowMin: vCreateTreatment.venousPressureLimitLowMin + lowMax: vCreateTreatment.venousPressureLimitLowMax + highMin: vCreateTreatment.venousPressureLimitHighMin + highMax: vCreateTreatment.venousPressureLimitHighMax + onLowSliderChanged: { + vCreateTreatment.venousPressureLimitLow = lowValue + } + onHighSliderChanged: { + vCreateTreatment.venousPressureLimitHigh = highValue + } + } + + SliderCreateTreatment { + id: _bloodPressureMeasurementInterval + text: "Blood Pressure Measurement Interval" + units: qsTr(" min") + min: vCreateTreatment.bloodPressureMeasureIntervalMin + max: vCreateTreatment.bloodPressureMeasureIntervalMax + step: 1 + stepSnap: true + onSliderChanged: { + vCreateTreatment.bloodPressureMeasureInterval = value + } + } + + SliderCreateTreatment { + id: _rinsebackFlowRate + text: "Rinseback Flow Rate" + units: qsTr(" mL/min") + min: vCreateTreatment.rinsebackFlowRateMin + max: vCreateTreatment.rinsebackFlowRateMax + step: 1 + stepSnap: true + onSliderChanged: { + vCreateTreatment.rinsebackFlowRate = value + } + } + TouchRect { id : _continueRect anchors.horizontalCenter: parent.horizontalCenter text.text: qsTr("CONTINUE") - button.onClicked: _root.clickedContinue() + backgroundColor: Colors.createTreatmentNotReady + borderColor: Colors.createTreatmentNotReady + textColor: Colors.createTrTextNotReady + button.onClicked: { + console.log("continue enabled: " + vCreateTreatment.continueEnabled); + if (vCreateTreatment.continueEnabled) { + _root.clickedContinue() + } + } + + function toggleEnabled(enabled) { + if (enabled) { + backgroundColor = Colors.createTreatmentActive + borderColor = Colors.createTreatmentActive + textColor = Colors.createTrTextReady + } else { + backgroundColor = Colors.createTreatmentNotReady + borderColor = Colors.createTreatmentNotReady + textColor = Colors.createTrTextNotReady + } + } } } } - states: State { - when: _flickable.movingVertically - PropertyChanges { - target: _verticalScrollBar - opacity: 0.8 + states: [ + State { + when: _flickable.movingVertically + PropertyChanges { + target: _verticalScrollBar + opacity: 0.8 + } } - } + ] ScrollBar { anchors.top: _flickable.top @@ -246,5 +340,50 @@ } } + Connections { target: vCreateTreatment + onContinueEnabledChanged: { + if (vCreateTreatment.continueEnabled) { + _continueRect.toggleEnabled(true) + } else { + _continueRect.toggleEnabled(false) + } + } + + onResetCreateTreatment: { + console.log("resetting create treatment"); + _bloodFlowRate.isActive = false; + _dialysateFlowRate.isActive = false; + _duration.isActive = false; + _heparinDispensingRate.isActive = false; + + _heparinBolusVolume.isActive = false; + _heparinStopTime.isActive = false; + + _salineBolus.setActive(false); + _acidConcentrate.setActive(false); + _bicarbonateConcentrate.setActive(false); + _dialyserType.setActive(false); + + _dialysateTemperature.isActive = false; + _arterialPressureLimits.isLowActive = false; + _arterialPressureLimits.isHighActive = false; + _venousPressureLimits.isLowActive = false; + _venousPressureLimits.isHighActive = false; + _bloodPressureMeasurementInterval.isActive = false; + _rinsebackFlowRate.isActive = false; + + } + + onFwValidationFailed: { + console.debug("Fw validation failed: " + reason); + } + + onBloodFlowRate_ValidationFailed: { + console.debug("Blood flow validation failed: " + reason); + } + } + + + } Index: sources/gui/qml/pages/treatment/TreatmentPrime.qml =================================================================== diff -u --- sources/gui/qml/pages/treatment/TreatmentPrime.qml (revision 0) +++ sources/gui/qml/pages/treatment/TreatmentPrime.qml (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,119 @@ +/*! + * + * Copyright (c) 2020 Diality Inc. - All Rights Reserved. + * \copyright \n + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, \n + * IN PART OR IN WHOLE, \n + * WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. \n + * + * \file TreatmentCreate.qml + * \author (last) Peter Lucia + * \date (last) 17-07-2020 + * \author (original) Behrouz NematiPour + * \date (original) 27-Jan-2020 + * + */ + +// Qt +import QtQuick 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.12 + +// Project +// Qml imports +import "qrc:/globals" +import "qrc:/components" + +/*! + * \brief ManagerHome is the screen + * which is the default screen in the "Manager" stack + */ +ScreenItem { id: _root + signal clickedBack() + signal clickedContinue() + backgroundRect.color: Colors.backgroundMainMenu + + TopMenuBarCreateTreatment { id: _topMenuBar + anchors.top: parent.top + anchors.left: parent.left + width: parent.width + onClickedBack: { + _root.clickedBack(); + + } + state: "prime" + } + + + Flickable { + id: _flickable + anchors.top: _topMenuBar.bottom + anchors.left: parent.left + anchors.bottom: parent.bottom + width: parent.width + contentWidth: parent.width + contentHeight: _column.implicitHeight + clip: true + + Column { + id: _column + spacing: Variables.cTreatmentSpacing + anchors.horizontalCenter: parent.horizontalCenter; + anchors.fill: parent; + + Text { id: _titleText + anchors.horizontalCenter: parent.horizontalCenter; + text: qsTr("Priming") + color: Colors.textMain + font.pixelSize: Fonts.fontPixelTitle + } + + TouchRect { id : _continueRect + anchors.horizontalCenter: parent.horizontalCenter + text.text: qsTr("CONTINUE TO TREATMENT") + button.onClicked: { + _root.clickedContinue() + } + } + } + } + + states: [ + State { + when: _flickable.movingVertically + PropertyChanges { + target: _verticalScrollBar + opacity: 0.8 + } + } + ] + + ScrollBar { + anchors.top: _flickable.top + anchors.bottom: _flickable.bottom + id: _verticalScrollBar + size: _flickable.height / _column.implicitHeight + active: true + anchors.right: _flickable.right + anchors.rightMargin: 5 + opacity: 0 + orientation: Qt.Vertical + position: _flickable.visibleArea.yPosition + + contentItem: Rectangle { + color: Colors.backgroundRangeRect + implicitWidth: 6 + radius: width / 2 + width: 3 + } + + } + + onVisibleChanged: { + if (visible) { + _mainMenu.hidden = true + } + } + + +} Index: sources/gui/qml/pages/treatment/TreatmentStack.qml =================================================================== diff -u -rc8eb6d0e29f8951a793b2f52d11a08b9902470ee -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/gui/qml/pages/treatment/TreatmentStack.qml (.../TreatmentStack.qml) (revision c8eb6d0e29f8951a793b2f52d11a08b9902470ee) +++ sources/gui/qml/pages/treatment/TreatmentStack.qml (.../TreatmentStack.qml) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -50,7 +50,7 @@ TreatmentHome { id: _treatmentHome onTreatmentStarted : push( _treatmentStart ) - onTreatmentCreated : push( _treatmentCreate) + onTreatmentCreated : { vCreateTreatment.onResetCreateTreatment(); push( _treatmentCreate); } } TreatmentStart { id: _treatmentStart @@ -72,8 +72,25 @@ TreatmentCreate { id: _treatmentCreate onClickedBack : pop() + onClickedContinue : {vCreateTreatment.onFinishedCreate(); } } + TreatmentConfirm { id: _treatmentConfirm + onClickedBack : pop() + onClickedConfirm : {vCreateTreatment.onFinishedConfirm(); } + } + + TreatmentPrime { id: _treatmentPrime + onClickedBack : pop() + onClickedContinue : {vCreateTreatment.onFinishedPrime(); } + } + + TreatmentBegin { id: _treatmentBegin + onClickedBack : pop() + onClickedStart : {vCreateTreatment.onStart(); } + } + + //// Treatment Adjustment Dialogs TreatmentAdjustmentFlow { id: _treatmentAdjustmentFlow onCloseClicked : close() @@ -197,4 +214,15 @@ _treatmentAdjustmentUltrafiltrationConfirm.notification.text = vTreatmentAdjustmentUltrafiltrationConfirm.text() } } - }} + } + + + Connections { target: vCreateTreatment + onShowConfirm : { push(_treatmentConfirm) } + onShowPrime : { push(_treatmentPrime) } + onShowBegin : { push(_treatmentBegin) } + } + + + +} Index: sources/main.h =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/main.h (.../main.h) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/main.h (.../main.h) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -48,14 +48,14 @@ extern bool gDisableTimeout; //--------------------------------------------------------------------------------// //--------------------------------------------------------------------------------// -#define DEBUG_PROPERTY_CHANGED(vVARIABLE) //qDebug() << "#" << #vVARIABLE << v##vVARIABLE; +#define DEBUG_PROPERTY_CHANGED(vVARIABLE, PREFIX) // qDebug() << "#" << #vVARIABLE << PREFIX##vVARIABLE; //--------------------------------------------------------------------------------// #define PROPERTY_SLOT( vTYPE , vVARIABLE ) \ protected : \ void vVARIABLE ( const vTYPE & v##vVARIABLE ) { \ static bool init = false; \ if ( !init || _##vVARIABLE != v##vVARIABLE ) { \ - DEBUG_PROPERTY_CHANGED(vVARIABLE) \ + DEBUG_PROPERTY_CHANGED(vVARIABLE, v) \ init = true; \ _##vVARIABLE = v##vVARIABLE; \ emit vVARIABLE##Changed( _##vVARIABLE ); \ @@ -65,7 +65,7 @@ #define TRIGGER_SLOT( vTYPE , vVARIABLE ) \ protected: \ void vVARIABLE ( const vTYPE & v##vVARIABLE ) { \ - DEBUG_PROPERTY_CHANGED(vVARIABLE) \ + DEBUG_PROPERTY_CHANGED(vVARIABLE, v) \ _##vVARIABLE = v##vVARIABLE; \ emit vVARIABLE##Triggered( _##vVARIABLE ); \ } @@ -167,4 +167,36 @@ //--------------------------------------------------------------------------------// #define REGISTER_TYPE(vTYPE) \ qmlRegisterType < vTYPE > (#vTYPE, 0, 1, #vTYPE); +#define GET_VARIABLE_NAME(VARIABLE) (#VARIABLE) +#define TREATMENT_PARAMETER(TYPE, NAME, DEFVALUE) \ +private: \ + TYPE _##NAME = DEFVALUE; \ + bool is##NAME##Set = false; \ +protected: \ + Q_PROPERTY(TYPE NAME \ + READ get_##NAME \ + WRITE set_##NAME \ + NOTIFY NAME##Changed) \ + void set_##NAME(const TYPE &p##NAME) { \ + static bool init = false; \ + if ( !init || _##NAME != p##NAME ) { \ + init = true; \ + _##NAME = p##NAME; \ + DEBUG_PROPERTY_CHANGED(NAME, _) \ + is##NAME##Set = true; \ + emit NAME##Changed(_##NAME); \ + onUserModifiedParameters(); \ + } \ + } \ + TYPE get_##NAME() const { \ + return _##NAME; \ + } \ + void reset_##NAME() { \ + _##NAME = DEFVALUE; \ + is##NAME##Set = false; \ + emit NAME##Changed(_##NAME); \ + } \ +Q_SIGNALS: \ + void NAME##Changed(const TYPE &p##NAME); \ + void NAME##_ValidationFailed(const QString &reason); Index: sources/model/mmodel.h =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/model/mmodel.h (.../mmodel.h) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/model/mmodel.h (.../mmodel.h) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -35,6 +35,8 @@ #include "mtreatmentadjustultrafiltrationeditresponse.h" #include "mtreatmentadjustultrafiltrationconfirmresponse.h" #include "mtreatmentadjustrequests.h" +#include "mtreatmentparameters.h" +#include "mtreatmentparametersresp.h" /*! * \brief Message interpretation instruction @@ -147,7 +149,8 @@ REGISTER_METATYPE( AdjustDurationResponseData ) \ REGISTER_METATYPE( AdjustUltrafiltrationStateResponseData ) \ REGISTER_METATYPE( AdjustUltrafiltrationEditResponseData ) \ - REGISTER_METATYPE( AdjustUltrafiltrationConfirmResponseData ) + REGISTER_METATYPE( AdjustUltrafiltrationConfirmResponseData ) \ + REGISTER_METATYPE( TreatmentData ) //===============================================================================// #define ACTION_RECEIVE_MODEL_BRIDGE_CONNECTIONS(vSOURCE) \ @@ -193,7 +196,8 @@ ACTION_RECEIVE_BRIDGE_DEFINITION( AdjustBloodDialysateResponseData ) \ ACTION_RECEIVE_BRIDGE_DEFINITION( AdjustDurationResponseData ) \ ACTION_RECEIVE_BRIDGE_DEFINITION( AdjustUltrafiltrationEditResponseData ) \ - ACTION_RECEIVE_BRIDGE_DEFINITION( AdjustUltrafiltrationConfirmResponseData ) + ACTION_RECEIVE_BRIDGE_DEFINITION( AdjustUltrafiltrationConfirmResponseData ) \ + ACTION_RECEIVE_BRIDGE_DEFINITION( TreatmentParametersRespData ) //--------------------------------------------------------------------------------// #define ADJUST_TRANSMT_MODEL_BRIDGE_DEFINITIONS \ ADJUST_TRANSMT_BRIDGE_DEFINITION( AdjustBloodDialysateRequestData ) \ @@ -233,6 +237,7 @@ ACTION_RECEIVE_SIGNAL( AdjustBloodDialysateResponseData ) \ ACTION_RECEIVE_SIGNAL( AdjustDurationResponseData ) \ ACTION_RECEIVE_SIGNAL( AdjustUltrafiltrationEditResponseData ) \ - ACTION_RECEIVE_SIGNAL( AdjustUltrafiltrationConfirmResponseData ) + ACTION_RECEIVE_SIGNAL( AdjustUltrafiltrationConfirmResponseData ) \ + ACTION_RECEIVE_SIGNAL( TreatmentParametersRespData ) //--------------------------------------------------------------------------------// //--------------------------------------------------------------------------------// Index: sources/model/mtreatmentparameters.cpp =================================================================== diff -u --- sources/model/mtreatmentparameters.cpp (revision 0) +++ sources/model/mtreatmentparameters.cpp (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,4 @@ +#include "mtreatmentparameters.h" +using namespace Model; + +TreatmentParameters::TreatmentParameters() {} Index: sources/model/mtreatmentparameters.h =================================================================== diff -u --- sources/model/mtreatmentparameters.h (revision 0) +++ sources/model/mtreatmentparameters.h (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,44 @@ +#ifndef MTREATMENTPARAMETERS_H +#define MTREATMENTPARAMETERS_H + +// Qt + +// Project +#include "types.h" +class tst_models; + +namespace Model { +class TreatmentParameters +{ + friend class::tst_models; +public: + TreatmentParameters(); + + struct Data { + quint32 bloodFlowRate = 0; // mL/min + quint32 dialysateFlowRate = 0; // mL/min + quint32 duration = 0; // minutes + quint32 heparinDispensingRate = 0; // mL/hr + quint32 heparinBolusVolume = 0; // mL + quint32 heparinStopTime = 0; // min + quint32 salineBolus = 0; // mL + quint32 acidConcentrate = 0; // + quint32 bicarbonateConcentrate = 0; // + quint32 dialyzerType = 0; // + quint32 dialysateTemp = 0; // Celsius + qint32 arterialPressureLimitLow = 0; // mmHg + qint32 arterialPressureLimitHigh = 0; // mmHg + qint32 venousPressureLimitLow = 0; // mmHg + qint32 venousPressureLimitHigh = 0; // mmHg + quint32 bloodPressureMeasureInterval = 0; // minutes + quint32 rinsebackFlowRate = 0; // mL/min + }; + + Data data; + +}; + +} + +typedef Model::TreatmentParameters::Data TreatmentData; +#endif // MTREATMENTPARAMETERS_H Index: sources/model/mtreatmentparametersresp.cpp =================================================================== diff -u --- sources/model/mtreatmentparametersresp.cpp (revision 0) +++ sources/model/mtreatmentparametersresp.cpp (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,148 @@ +#include "mtreatmentparametersresp.h" +using namespace Model; + +TreatmentParametersResp::TreatmentParametersResp() {} + +/** + * @brief TreatmentParametersResp::toVariantList + * Converts the response data to a QVariantList + * @param list (&QVariantlist) - the list to write the data to + */ +void TreatmentParametersResp::toVariantList(QVariantList &list) const +{ + list += _data.requestValid.value; + list += _data.bloodFlowRate.value; + list += _data.dialysateFlowRate.value; + list += _data.duration.value; + list += _data.heparinDispensingRate.value; + list += _data.heparinBolusVolume.value; + list += _data.heparinStopTime.value; + list += _data.salineBolus.value; + list += _data.acidConcentrate.value; + list += _data.bicarbonateConcentrate.value; + list += _data.dialyzerType.value; + list += _data.dialysateTemp.value; + list += _data.arterialPressureLimitLow.value; + list += _data.arterialPressureLimitHigh.value; + list += _data.venousPressureLimitLow.value; + list += _data.venousPressureLimitHigh.value; + list += _data.bloodPressureMeasureInterval.value; + list += _data.rinsebackFlowRate.value; + +} + +TreatmentParametersRespData TreatmentParametersResp::fromVariantList(const QVariantList &list) +{ + Data data; + if (list.length() != 18) + { + qDebug() << "Invalid QVariant List in " << __FUNCTION__; + return data; + } + data.requestValid = list[0].toUInt(); + data.bloodFlowRate = list[1].toUInt(); + data.dialysateFlowRate = list[2].toUInt(); + data.duration = list[3].toUInt(); + data.heparinDispensingRate = list[4].toUInt(); + data.heparinBolusVolume = list[5].toUInt(); + data.heparinStopTime = list[6].toUInt(); + data.salineBolus = list[7].toUInt(); + data.acidConcentrate = list[8].toUInt(); + data.bicarbonateConcentrate = list[9].toUInt(); + data.dialyzerType = list[10].toUInt(); + data.dialysateTemp = list[11].toUInt(); + data.arterialPressureLimitLow = list[12].toUInt(); + data.arterialPressureLimitHigh = list[13].toUInt(); + data.venousPressureLimitLow = list[14].toUInt(); + data.venousPressureLimitHigh = list[15].toUInt(); + data.bloodPressureMeasureInterval = list[16].toUInt(); + data.rinsebackFlowRate = list[17].toUInt(); + return data; +} + +bool TreatmentParametersResp::fromByteArray(const QByteArray &vByteArray, int *vIndex) { + int index = 0; // message data start position + if (GetValue(vByteArray, index, _data.requestValid )) + if (GetValue(vByteArray, index, _data.bloodFlowRate )) + if (GetValue(vByteArray, index, _data.dialysateFlowRate )) + if (GetValue(vByteArray, index, _data.duration )) + if (GetValue(vByteArray, index, _data.heparinDispensingRate )) + if (GetValue(vByteArray, index, _data.heparinBolusVolume )) + if (GetValue(vByteArray, index, _data.heparinStopTime )) + if (GetValue(vByteArray, index, _data.salineBolus )) + if (GetValue(vByteArray, index, _data.acidConcentrate )) + if (GetValue(vByteArray, index, _data.bicarbonateConcentrate )) + if (GetValue(vByteArray, index, _data.dialyzerType )) + if (GetValue(vByteArray, index, _data.dialysateTemp )) + if (GetValue(vByteArray, index, _data.arterialPressureLimitLow )) + if (GetValue(vByteArray, index, _data.arterialPressureLimitHigh )) + if (GetValue(vByteArray, index, _data.venousPressureLimitLow )) + if (GetValue(vByteArray, index, _data.venousPressureLimitHigh )) + if (GetValue(vByteArray, index, _data.bloodPressureMeasureInterval )) + if (GetValue(vByteArray, index, _data.rinsebackFlowRate )) + return true; + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } + else { if(vIndex) *vIndex = index; return false; } +} + +QString TreatmentParametersResp::toString() const { + return QString(stringPrefix + "(%0, %1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16, %17)") + .arg(_data.requestValid.value) + .arg(_data.bloodFlowRate.value) + .arg(_data.dialysateFlowRate.value) + .arg(_data.duration.value) + .arg(_data.heparinDispensingRate.value) + .arg(_data.heparinBolusVolume.value) + .arg(_data.heparinStopTime.value) + .arg(_data.salineBolus.value) + .arg(_data.acidConcentrate.value) + .arg(_data.bicarbonateConcentrate.value) + .arg(_data.dialyzerType.value) + .arg(_data.dialysateTemp.value) + .arg(_data.arterialPressureLimitLow.value) + .arg(_data.arterialPressureLimitHigh.value) + .arg(_data.venousPressureLimitLow.value) + .arg(_data.venousPressureLimitHigh.value) + .arg(_data.bloodPressureMeasureInterval.value) + .arg(_data.rinsebackFlowRate.value); +} + +TreatmentParametersRespData TreatmentParametersResp::data() const { + Data data; + data.requestValid = _data.requestValid.value; + data.bloodFlowRate = _data.bloodFlowRate.value; + data.dialysateFlowRate = _data.dialysateFlowRate.value; + data.duration = _data.duration.value; + data.heparinDispensingRate = _data.heparinDispensingRate.value; + data.heparinBolusVolume = _data.heparinBolusVolume.value; + data.heparinStopTime = _data.heparinStopTime.value; + data.salineBolus = _data.salineBolus.value; + data.acidConcentrate = _data.acidConcentrate.value; + data.bicarbonateConcentrate = _data.bicarbonateConcentrate.value; + data.dialyzerType = _data.dialyzerType.value; + data.dialysateTemp = _data.dialysateTemp.value; + data.arterialPressureLimitLow = _data.arterialPressureLimitLow.value; + data.arterialPressureLimitHigh = _data.arterialPressureLimitHigh.value; + data.venousPressureLimitLow = _data.venousPressureLimitLow.value; + data.venousPressureLimitHigh = _data.venousPressureLimitHigh.value; + data.bloodPressureMeasureInterval = _data.bloodPressureMeasureInterval.value; + data.rinsebackFlowRate = _data.rinsebackFlowRate.value; + return data; +} + Index: sources/model/mtreatmentparametersresp.h =================================================================== diff -u --- sources/model/mtreatmentparametersresp.h (revision 0) +++ sources/model/mtreatmentparametersresp.h (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,79 @@ +#ifndef MTREATMENTPARAMETERSRESP_H +#define MTREATMENTPARAMETERSRESP_H + +// Qt + +// Project +#include "types.h" + + +class tst_models; + +namespace Model { +class TreatmentParametersResp +{ + friend class::tst_models; +public: + TreatmentParametersResp(); + + struct Data { + quint32 requestValid = 0; + quint32 bloodFlowRate = 0; + quint32 dialysateFlowRate = 0; + quint32 duration = 0; + quint32 heparinDispensingRate = 0; + quint32 heparinBolusVolume = 0; + quint32 heparinStopTime = 0; + quint32 salineBolus = 0; + quint32 acidConcentrate = 0; + quint32 bicarbonateConcentrate = 0; + quint32 dialyzerType = 0; + quint32 dialysateTemp = 0; + quint32 arterialPressureLimitLow = 0; + quint32 arterialPressureLimitHigh = 0; + quint32 venousPressureLimitLow = 0; + quint32 venousPressureLimitHigh = 0; + quint32 bloodPressureMeasureInterval = 0; + quint32 rinsebackFlowRate = 0; + }; + + Data fromVariantList(const QVariantList &list); + void toVariantList(QVariantList &list) const; + bool fromByteArray(const QByteArray &vByteArray, int *vIndex = nullptr); + QString toString() const; + Data data() const; + +protected: + struct _Data { + + Types::U32 requestValid ; + Types::U32 bloodFlowRate ; + Types::U32 dialysateFlowRate ; + Types::U32 duration ; + Types::U32 heparinDispensingRate ; + Types::U32 heparinBolusVolume ; + Types::U32 heparinStopTime ; + Types::U32 salineBolus ; + Types::U32 acidConcentrate ; + Types::U32 bicarbonateConcentrate ; + Types::U32 dialyzerType ; + Types::U32 dialysateTemp ; + Types::U32 arterialPressureLimitLow ; + Types::U32 arterialPressureLimitHigh ; + Types::U32 venousPressureLimitLow ; + Types::U32 venousPressureLimitHigh ; + Types::U32 bloodPressureMeasureInterval ; + Types::U32 rinsebackFlowRate ; + + } _data; + + +private: + QString stringPrefix = "Treatment Parameters Response"; + +}; + +} + +typedef Model::TreatmentParametersResp::Data TreatmentParametersRespData; +#endif // MTREATMENTPARAMETERSRESP_H Index: sources/storage/filehandler.cpp =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/storage/filehandler.cpp (.../filehandler.cpp) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/storage/filehandler.cpp (.../filehandler.cpp) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -43,6 +43,15 @@ err << mCritical << endl; } +/*! + * \brief FileHandler::write + * \details Writes the content of vContent into the file vFileName. + * \param vFileName - Source file name + * \param vContent - The content which is going to be written in the file. + * \param vAppend - if set to true the content will be appended at the end of the file. + * \param id - contains the request id, defaults to -1 + * \return false if file can't be opened. + */ bool FileHandler::write(const QString &vFileName, const QString &vContent, bool vAppend) { QFile file(vFileName); @@ -59,6 +68,7 @@ return true; } + /*! * \brief FileHandler::read * \details reads file vFilename content into vContent variable. @@ -79,6 +89,48 @@ } /*! + * \brief FileHandler::readCSV + * \details reads the provided filename's content into the vContent variable. + * \param vFileName - Source file name + * \param vContent - The content of the file which will be written to when done. + * \return false if file can't be read + */ +bool FileHandler::readCSV(const QString &vFileName, QString &vContent) +{ + QFile file(vFileName); + if (! file.open(QFile::Text | QFile::ReadOnly)) { + errOut(QObject::tr("Can't open file for read (%1).Possible corrupted file system").arg(vFileName)); + return false; + } + QTextStream in(&file); + vContent = in.readAll(); + return true; +} + +/*! + * \brief FileHandler::readCSV + * \details reads the provided filename's JSON content into the vContent variable. + * \param vFileName - Source file name + * \param vContent - The content of the file which will be written to when done. + * \return false if file can't be read + */ +bool FileHandler::readJSON(const QString &vFileName, QJsonObject &vContent) +{ + QFile file(vFileName); + if (! file.open(QFile::Text | QFile::ReadOnly)) { + errOut(QObject::tr("Can't open file for read (%1).Possible corrupted file system").arg(vFileName)); + return false; + } + QTextStream in(&file); + QString content = in.readAll(); + + + QJsonDocument doc = QJsonDocument::fromJson(content.toUtf8()); + vContent = doc.object(); + return true; +} + +/*! * \brief FileHandler::copyFolder * \details Copies all the file and folders recursively. * \param vSource - The source folder Index: sources/storage/filehandler.h =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/storage/filehandler.h (.../filehandler.h) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/storage/filehandler.h (.../filehandler.h) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -16,6 +16,9 @@ // Qt #include +#include +#include +#include namespace Storage { @@ -32,7 +35,9 @@ public: static bool write(const QString &vFileName, const QString &vContent, bool vAppend = true); - static bool read (const QString &vFileName, QString &vContent); + static bool read (const QString &vFileName, QString &vContent); + static bool readCSV(const QString &vFileName, QString &vContent); + static bool readJSON(const QString &vFileName, QJsonObject &vContent); static int copyFolder(const QString &vSource, const QString &vDestination); }; Index: sources/storage/filesaver.cpp =================================================================== diff -u --- sources/storage/filesaver.cpp (revision 0) +++ sources/storage/filesaver.cpp (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,40 @@ +#include "filesaver.h" + + +// Qt +#include +#include + +// Project +#include "filehandler.h" + + +using namespace Storage; + +FileSaver::FileSaver(QObject *parent) : QObject(parent) +{ + connect(&_futureWatcher, SIGNAL(finished()), + this , SLOT(onFileSaved())); +} + +/** + * @brief FileSaver::concurrentSave + * @param filename (QString) contains the path to the file to be written to + * @param content (QString) the content to write to the file + * @param append (bool) if True, append the content. Otherwise, overwrite it + * @return (int) the job ID number, emitted by this class once the file has been saved + */ +void FileSaver::concurrentSave(const QString &filename, const QString &content, bool append) +{ + QFuture future = QtConcurrent::run(&FileHandler::write, filename, content, append); + _futureWatcher.setFuture(future); +} + +/** + * @brief FileSaver::onFileSaved + * Emits a QPair, true if the save was succesful and the job id of the file that has been saved + */ +void FileSaver::onFileSaved() +{ + emit fileSaved(_futureWatcher.result()); +} Index: sources/storage/filesaver.h =================================================================== diff -u --- sources/storage/filesaver.h (revision 0) +++ sources/storage/filesaver.h (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,38 @@ +#ifndef FILESAVER_H +#define FILESAVER_H + +// Qt +#include +#include +#include + +// Project +#include "main.h" + +// Define +#define _FileSaver FileSaver::I() + +namespace Storage { + +class FileSaver : public QObject +{ + Q_OBJECT + +SINGLETON(FileSaver); + +private: + QFutureWatcher _futureWatcher; + +signals: + void fileSaved(bool result); + +public slots: + void concurrentSave(const QString &filename, const QString &content, bool append); // static ? + +private slots: + void onFileSaved(); +}; + +} + +#endif // FILESAVER_H Index: sources/storage/storageglobals.cpp =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/storage/storageglobals.cpp (.../storageglobals.cpp) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/storage/storageglobals.cpp (.../storageglobals.cpp) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -12,8 +12,11 @@ * \date (original) 02-Jan-2020 * */ - +// Qt +#include +// Project #include "storageglobals.h" +using namespace std; namespace Storage { @@ -25,4 +28,15 @@ const char *Log_Base_Path_Name = "/media/sd-card/"; const char *Log_Base_Path_Name_Location = "/media/sd-card/log/"; const char *Log_File_Name = "denali.log"; + + // Treatment +#ifdef DEBUG + const char *Treatment_Base_Path_Name = "/home/denali/Desktop/treatment/"; + const char *Treatment_Profiles_Dir = "/home/denali/Desktop/treatment/profiles/"; + const char *Treatment_Parameter_Ranges_Path = "/home/denali/Desktop/treatment/denali.conf"; +#else + const char *Treatment_Base_Path_Name = "/media/sd-card/treatment/"; + const char *Treatment_Profiles_Dir = "/media/sd-card/treatment/profiles/"; + const char *Treatment_Parameter_Ranges_Path = "/media/sd-card/treatment/denali.conf"; +#endif } Index: sources/storage/storageglobals.h =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/storage/storageglobals.h (.../storageglobals.h) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/storage/storageglobals.h (.../storageglobals.h) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -27,4 +27,8 @@ extern const char *Log_Base_Path_Name ; extern const char *Log_Base_Path_Name_Location; extern const char *Log_File_Name ; + + // Treatment + extern const char *Treatment_Profiles_Dir ; + extern const char *Treatment_Parameter_Ranges_Path ; } Index: sources/view/VCreateTreatment.cpp =================================================================== diff -u --- sources/view/VCreateTreatment.cpp (revision 0) +++ sources/view/VCreateTreatment.cpp (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,654 @@ +#include "VCreateTreatment.h" + +// Qt + +// Project +#include "filehandler.h" +#include "MsgDefs.h" + +using namespace Gui; +using namespace View; +using namespace Storage; + + +VCreateTreatment::VCreateTreatment(QObject *parent) : QObject(parent) +{ + connect(&_FileSaver, SIGNAL(fileSaved(bool)), + this, SLOT(onFinishedSaveNewTreatment(bool))); + + connect(this, SIGNAL(validateParamsWithFW(GuiActionType,QVariantList)), + &_GuiController, SLOT(doActionTransmit(GuiActionType,QVariantList))); + + connect(&_GuiController, SIGNAL(didActionReceive(GuiActionType,QVariantList)), + this, SLOT(onFWValidationResponse(GuiActionType,QVariantList))); + + loadTreatmentParameterRanges(); +} + +QJsonObject VCreateTreatment::loadTreatmentParameterRanges() +{ + QJsonObject obj; + if (!FileHandler::readJSON(Treatment_Parameter_Ranges_Path, obj)) + { + // TODO: handle error + } + + foreach (const QString& key, obj.keys()) + { + QJsonValue value = obj.value(key); + + if (key == GET_VARIABLE_NAME(bloodFlowRateMin)) + _bloodFlowRateMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(bloodFlowRateMax)) + _bloodFlowRateMax = value.toInt(); + else if (key == GET_VARIABLE_NAME(dialysateFlowRateMin)) + _dialysateFlowRateMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(dialysateFlowRateMax)) + _dialysateFlowRateMax = value.toInt(); + else if (key == GET_VARIABLE_NAME(durationMin)) + _durationMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(durationMax)) + _durationMax = value.toInt(); + else if (key == GET_VARIABLE_NAME(heparinDispensingRateMin)) + _heparinDispensingRateMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(heparinDispensingRateMax)) + _heparinDispensingRateMax = value.toInt(); + else if (key == GET_VARIABLE_NAME(heparinBolusVolumeMin)) + _heparinBolusVolumeMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(heparinBolusVolumeMax)) + _heparinBolusVolumeMax = value.toInt(); + else if (key == GET_VARIABLE_NAME(heparinStopTimeMin)) + _heparinStopTimeMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(heparinStopTimeMax)) + _heparinStopTimeMax = value.toInt(); + //options + else if (key == GET_VARIABLE_NAME(salineBolusOptions)) + _salineBolusOptions = jsonArrayToStringList(value.toArray()); + else if (key == GET_VARIABLE_NAME(acidConcentrateOptions)) + _acidConcentrateOptions = jsonArrayToStringList(value.toArray()); + else if (key == GET_VARIABLE_NAME(acidConcentrateOptions)) + _acidConcentrateOptions = jsonArrayToStringList(value.toArray()); + else if (key == GET_VARIABLE_NAME(bicarbonateConcentrateOptions)) + _bicarbonateConcentrateOptions = jsonArrayToStringList(value.toArray()); + else if (key == GET_VARIABLE_NAME(dialyzerTypeOptions)) + _dialyzerTypeOptions = jsonArrayToStringList(value.toArray()); + + else if (key == GET_VARIABLE_NAME(dialysateTempMin)) + _dialysateTempMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(dialysateTempMax)) + _dialysateTempMax = value.toInt(); + // arterial + else if (key == GET_VARIABLE_NAME(arterialPressureLimitLowMin)) + _arterialPressureLimitLowMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(arterialPressureLimitLowMax)) + _arterialPressureLimitLowMax = value.toInt(); + else if (key == GET_VARIABLE_NAME(arterialPressureLimitHighMin)) + _arterialPressureLimitHighMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(arterialPressureLimitHighMax)) + _arterialPressureLimitHighMax = value.toInt(); + //venous + else if (key == GET_VARIABLE_NAME(venousPressureLimitLowMin)) + _venousPressureLimitLowMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(venousPressureLimitLowMax)) + _venousPressureLimitLowMax = value.toInt(); + else if (key == GET_VARIABLE_NAME(venousPressureLimitHighMin)) + _venousPressureLimitHighMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(venousPressureLimitHighMax)) + _venousPressureLimitHighMax = value.toInt(); + + else if (key == GET_VARIABLE_NAME(bloodPressureMeasureIntervalMin)) + _bloodPressureMeasureIntervalMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(bloodPressureMeasureIntervalMax)) + _bloodPressureMeasureIntervalMax = value.toInt(); + + else if (key == GET_VARIABLE_NAME(rinsebackFlowRateMin)) + _rinsebackFlowRateMin = value.toInt(); + else if (key == GET_VARIABLE_NAME(rinsebackFlowRateMax)) + _rinsebackFlowRateMax = value.toInt(); + else + { + qDebug() << "Invalid treatment parameter range: " << key; + LOG_EVENT(tr("Invalid treatment parameter found: %0").arg(key)); + } + } + + + return obj; + +} + +/** + * @brief VCreateTreatment::onResetCreateTreatment + * Resets the create treatment page to the default values. + * Disables the continue button. + */ +void VCreateTreatment::onResetCreateTreatment() +{ + reset_bloodFlowRate(); + reset_dialysateFlowRate(); + reset_duration(); + reset_heparinDispensingRate(); + reset_heparinBolusVolume(); + reset_heparinStopTime(); + reset_salineBolusVolume(); + reset_acidConcentrate(); + reset_bicarbonateConcentrate(); + reset_dialyzerType(); + reset_arterialPressureLimitLow(); + reset_arterialPressureLimitHigh(); + reset_venousPressureLimitLow(); + reset_venousPressureLimitHigh(); + reset_bloodPressureMeasureInterval(); + reset_rinsebackFlowRate(); + + continueEnabled(false); + + emit resetCreateTreatment(); +} + + +/** + * @brief VCreateTreatment::jsonArrayToStringList + * Converts a jsonarray of strings to a QStringList + * @param arr (QJsonArray) to convert + * @return (QStringList) The list of strings in the array + */ +QStringList VCreateTreatment::jsonArrayToStringList(const QJsonArray &arr) +{ + QStringList result; + foreach (const QJsonValue &val, arr) { + result.append(val.toString()); + } + return result; +} + +/** + * @brief VCreateTreatment::setTreatmentData + * Assigns treatment parameters to the treatment data structure. + */ +void VCreateTreatment::setTreatmentData() { + + treatmentData.bloodFlowRate = _bloodFlowRate; + treatmentData.dialysateFlowRate = _dialysateFlowRate; + treatmentData.duration = _duration; + treatmentData.heparinDispensingRate = _heparinDispensingRate; + treatmentData.heparinBolusVolume = _heparinBolusVolume; + treatmentData.heparinStopTime = _heparinStopTime; + treatmentData.salineBolus = _salineBolusVolume; + + treatmentData.acidConcentrate = _acidConcentrate; + treatmentData.bicarbonateConcentrate = _bicarbonateConcentrate; + treatmentData.dialyzerType = _dialyzerType; + treatmentData.dialysateTemp = _dialysateTemp; + treatmentData.arterialPressureLimitLow = _arterialPressureLimitLow; + treatmentData.arterialPressureLimitHigh = _arterialPressureLimitHigh; + treatmentData.venousPressureLimitLow = _venousPressureLimitLow; + treatmentData.venousPressureLimitHigh = _venousPressureLimitHigh; + treatmentData.bloodPressureMeasureInterval = _bloodPressureMeasureInterval; + treatmentData.rinsebackFlowRate = _rinsebackFlowRate; +} + +/** + * @brief VCreateTreatment::onFinishedCreate + * Validates the treatment profile locally, then requests validation of it with FW + */ +void VCreateTreatment::onFinishedCreate() { + + setTreatmentData(); + + qDebug() << treatmentData.bloodFlowRate; + qDebug() << treatmentData.dialysateFlowRate; + qDebug() << treatmentData.duration; + qDebug() << treatmentData.heparinDispensingRate; + qDebug() << treatmentData.heparinBolusVolume; + qDebug() << treatmentData.heparinStopTime; + qDebug() << treatmentData.salineBolus; + + qDebug() << treatmentData.acidConcentrate; + qDebug() << treatmentData.bicarbonateConcentrate; + qDebug() << treatmentData.dialyzerType; + qDebug() << treatmentData.dialysateTemp; + qDebug() << treatmentData.arterialPressureLimitLow; + qDebug() << treatmentData.arterialPressureLimitHigh; + qDebug() << treatmentData.venousPressureLimitLow; + qDebug() << treatmentData.venousPressureLimitHigh; + qDebug() << treatmentData.bloodPressureMeasureInterval; + qDebug() << treatmentData.rinsebackFlowRate; + + if (!validate(treatmentData)) + { + qDebug() << "Local create treatment validation failed."; + LOG_EVENT("Local create treatment validation failed."); + return; + } + + +#ifdef DEBUG + emit showConfirm(); +#else + // TODO: Ask FW to validate selected parameters + QVariantList messageData = { + treatmentData.bloodFlowRate, + treatmentData.dialysateFlowRate, + treatmentData.duration, + treatmentData.heparinDispensingRate, + treatmentData.heparinBolusVolume, + treatmentData.heparinStopTime, + treatmentData.salineBolus, + treatmentData.acidConcentrate, + treatmentData.bicarbonateConcentrate, + treatmentData.dialyzerType, + treatmentData.dialysateTemp, + treatmentData.arterialPressureLimitLow, + treatmentData.arterialPressureLimitHigh, + treatmentData.venousPressureLimitLow, + treatmentData.venousPressureLimitHigh, + treatmentData.bloodPressureMeasureInterval, + treatmentData.rinsebackFlowRate + }; + GuiActionType messageAction = GuiActions::CreateTreatmentReq; + + emit validateParamsWithFW(messageAction, messageData); + + qDebug() << "Requesting FW validation of new treatment parameters"; + LOG_EVENT("Requesting FW validation of new treatment parameters"); + +#endif +} + +QString VCreateTreatment::enumToString(GuiRequestReasons vEnum) +{ + const QMetaObject *mo = qt_getEnumMetaObject(vEnum); + int enumIdx = mo->indexOfEnumerator(qt_getEnumName(vEnum)); + QString mText = mo->enumerator(enumIdx).valueToKey(vEnum); + if ( ! mText.isEmpty() ) { + return mText; + } + return QString("[%1] Unknown Rejection Reason").arg(vEnum); +} + +void VCreateTreatment::onFWValidationResponse(GuiActionType actionType, QVariantList messageData) { + + Q_UNUSED(actionType) + if (actionType != GuiActionType::CreateTreatmentRsp) + { + QString logMsg = tr("Invalid action type received in %0").arg(__FUNCTION__); + qDebug() << logMsg; + LOG_ERROR(logMsg); + return; + } + + Model::TreatmentParametersResp response; + TreatmentParametersRespData data = response.fromVariantList(messageData); + + bool success = true; + if (data.requestValid != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit fwValidationFailed(enumToString(static_cast(data.requestValid))); + } + if (data.bloodFlowRate != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit bloodFlowRate_ValidationFailed(enumToString(static_cast(data.bloodFlowRate))); + } + if (data.dialysateFlowRate != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit dialysateFlowRate_ValidationFailed(enumToString(static_cast(data.dialysateFlowRate))); + } + if (data.duration != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit duration_ValidationFailed(enumToString(static_cast(data.duration))); + } + if (data.heparinDispensingRate != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit heparinBolusVolume_ValidationFailed(enumToString(static_cast(data.heparinDispensingRate))); + } + if (data.heparinBolusVolume != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + + success = false; + emit heparinBolusVolume_ValidationFailed(enumToString(static_cast(data.heparinBolusVolume))); + } + if (data.heparinStopTime != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit heparinStopTime_ValidationFailed(enumToString(static_cast(data.heparinStopTime))); + } + if (data.salineBolus != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit salineBolusVolume_ValidationFailed(enumToString(static_cast(data.salineBolus))); + } + if (data.acidConcentrate != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit acidConcentrate_ValidationFailed(enumToString(static_cast(data.acidConcentrate))); + } + if (data.bicarbonateConcentrate != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit bicarbonateConcentrate_ValidationFailed(enumToString(static_cast(data.bicarbonateConcentrate))); + } + if (data.dialyzerType != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit dialysateFlowRate_ValidationFailed(enumToString(static_cast(data.dialyzerType))); + } + if (data.dialysateTemp != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit dialysateTemp_ValidationFailed(enumToString(static_cast(data.dialysateTemp))); + } + if (data.arterialPressureLimitLow != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit arterialPressureLimitLow_ValidationFailed(enumToString(static_cast(data.arterialPressureLimitLow))); + } + if (data.arterialPressureLimitHigh != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit arterialPressureLimitHigh_ValidationFailed(enumToString(static_cast(data.arterialPressureLimitHigh))); + } + if (data.venousPressureLimitLow != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit venousPressureLimitLow_ValidationFailed(enumToString(static_cast(data.venousPressureLimitLow))); + } + if (data.venousPressureLimitHigh != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit venousPressureLimitHigh_ValidationFailed(enumToString(static_cast(data.venousPressureLimitHigh))); + } + if (data.bloodPressureMeasureInterval != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit bloodFlowRate_ValidationFailed(enumToString(static_cast(data.bloodPressureMeasureInterval))); + } + if (data.rinsebackFlowRate != Gui::GuiRequestReasons::REQUEST_REJECT_REASON_NONE) { + success = false; + emit rinsebackFlowRate_ValidationFailed(enumToString(static_cast(data.rinsebackFlowRate))); + } + + qDebug() << "fw validation success = " << success; + + if (success) + emit showConfirm(); + +} + +/** + * @brief VCreateTreatment::onFinishedConfirm + * Emits treatment data to gui controller, + * who emits to application controller and the + * application controller will save the data to disk. + */ +void VCreateTreatment::onFinishedConfirm() { + qDebug() << "Finished create treatment confirm..."; + + + QJsonObject obj { + {"bloodFlowRate", QString::number(treatmentData.bloodFlowRate)}, + {"dialysateFlowRate", QString::number(treatmentData.dialysateFlowRate)}, + {"duration", QString::number(treatmentData.duration)}, + {"heparinDispensingRate", QString::number(treatmentData.heparinDispensingRate)}, + {"heparinBolusVolume", QString::number(treatmentData.heparinBolusVolume)}, + {"heparinStopTime", QString::number(treatmentData.heparinStopTime)}, + {"acidConcentrate", QString::number(treatmentData.acidConcentrate)}, + {"bicarbonateConcentrate", QString::number(treatmentData.bicarbonateConcentrate)}, + {"dialyzerType", QString::number(treatmentData.dialyzerType)}, + {"dialysateTemp", QString::number(treatmentData.dialysateTemp)}, + {"arterialPressureLimitLow", QString::number(treatmentData.arterialPressureLimitLow)}, + {"arterialPressureLimitHigh", QString::number(treatmentData.arterialPressureLimitHigh)}, + {"venousPressureLimitLow", QString::number(treatmentData.venousPressureLimitLow)}, + {"venousPressureLimitHigh", QString::number(treatmentData.venousPressureLimitHigh)}, + {"bloodPressureMeasureInterval",QString::number(treatmentData.bloodPressureMeasureInterval)}, + {"rinsebackFlowRate", QString::number(treatmentData.rinsebackFlowRate)} + }; + + saveNewTreatment(obj); + + emit didCreateTreatment(treatmentData); + emit showPrime(); + +} + +/** + * @brief ApplicationController::saveNewTreatment + * Saves a new treatment to the filesystem. + * @param doc - QJsonDocument containing the new treatment parameters. + */ +void VCreateTreatment::saveNewTreatment(QJsonObject obj) +{ + QJsonDocument document(obj); + int i = 0; + while (QFile(QString("%0treatment%1.json").arg(Treatment_Profiles_Dir).arg(i)).exists()) + { + i++; + } + QString filename = QString("%0treatment%1.json").arg(Treatment_Profiles_Dir).arg(i); + _FileSaver.concurrentSave(filename, document.toJson(), false); + +} + +void VCreateTreatment::onFinishedSaveNewTreatment(bool success) +{ + if (success) { + qDebug() << "------------------> Saved a new treatment."; + } else { + qDebug() << "------------------> Failed to save new treatment."; + } +} + +/** + * @brief VCreateTreatment::onFnishedPrime + * Called when priming qml selections are complete. + * TODO: Placed here for now. Likely will be moved eventually. + */ +void VCreateTreatment::onFinishedPrime() { + qDebug() << "Finished create treatment prime..."; + emit showBegin(); + +} + +/** + * @brief VCreateTreatment::start + * Called when user is ready to begin a new treatment. + * TODO: Placed here for now. Likely will be moved eventually. + */ +void VCreateTreatment::onStart() { + qDebug() << "Starting Begin Treatment..."; + +} + +/** + * @brief VCreateTreatment::validate + * Validates the create new treatment input. + * @param vData - the selected TreatmentData + * @return true on success, false otherwise. + */ +bool VCreateTreatment::validate(const TreatmentData &vData) +{ + bool success = true; + + if (!isbloodFlowRateSet) + success = false; + + if (!isdialysateFlowRateSet) + success = false; + + if (!isdurationSet) + success = false; + + if (!isheparinDispensingRateSet) + success = false; + + if (!isheparinBolusVolumeSet) + success = false; + + if (!issalineBolusVolumeSet) + success = false; + + if (!isacidConcentrateSet) + success = false; + + if (!isbicarbonateConcentrateSet) + success = false; + + if (!isdialyzerTypeSet) + success = false; + + if (!isdialysateTempSet) + success = false; + + if (!isarterialPressureLimitLowSet) + success = false; + + if (!isarterialPressureLimitHighSet) + success = false; + + if (!isvenousPressureLimitLowSet) + success = false; + + if (!isvenousPressureLimitHighSet) + success = false; + + if (!isbloodPressureMeasureIntervalSet) + success = false; + + if (!isrinsebackFlowRateSet) + success = false; + + if (!success) { + qDebug() << "Not all values are set yet."; + return false; + } + + if (vData.bloodFlowRate < _bloodFlowRateMin || + vData.bloodFlowRate > _bloodFlowRateMax) + { + emit bloodFlowRate_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + if (vData.dialysateFlowRate < _dialysateFlowRateMin || + vData.dialysateFlowRate > _dialysateFlowRateMax ) + { + emit dialysateFlowRate_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + if (vData.duration < _durationMin || vData.duration > _durationMax) + { + emit duration_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + if (vData.heparinDispensingRate < _heparinDispensingRateMin || + vData.heparinDispensingRate > _heparinDispensingRateMax) + { + emit heparinDispensingRate_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + if (vData.heparinBolusVolume < _heparinBolusVolumeMin || + vData.heparinBolusVolume > _heparinBolusVolumeMax) + { + emit heparinBolusVolume_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + + if (vData.heparinStopTime < _heparinStopTimeMin || + vData.heparinStopTime > _heparinStopTimeMax) + { + emit heparinStopTime_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + + if (!indexInItems(vData.salineBolus, _salineBolusOptions)) + { + emit salineBolusVolume_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + if (!indexInItems(vData.acidConcentrate, _acidConcentrateOptions)) + { + emit acidConcentrate_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + if (!indexInItems(vData.bicarbonateConcentrate, _bicarbonateConcentrateOptions)) + { + emit bicarbonateConcentrate_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + if (!indexInItems(vData.dialyzerType, _dialyzerTypeOptions)) + { + emit dialyzerType_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + if (vData.dialysateTemp < _dialysateTempMin || + vData.dialysateTemp > _dialysateTempMax) + { + emit dialysateTemp_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + if (vData.arterialPressureLimitLow < _arterialPressureLimitLowMin || + vData.arterialPressureLimitLow > _arterialPressureLimitLowMax || + vData.arterialPressureLimitLow > vData.arterialPressureLimitHigh) + { + emit arterialPressureLimitLow_ValidationFailed(uiRejections.value(LOW_HIGH_INCOMPATIBLE)); + success = false; + } + if (vData.arterialPressureLimitHigh < _arterialPressureLimitHighMin || + vData.arterialPressureLimitHigh > _arterialPressureLimitHighMax || + vData.arterialPressureLimitHigh < vData.arterialPressureLimitLow) + { + emit arterialPressureLimitHigh_ValidationFailed(uiRejections.value(LOW_HIGH_INCOMPATIBLE)); + success = false; + } + if (vData.venousPressureLimitLow < _venousPressureLimitLowMin || + vData.venousPressureLimitLow > _venousPressureLimitLowMax || + vData.venousPressureLimitLow > vData.venousPressureLimitHigh) + { + emit venousPressureLimitLow_ValidationFailed(uiRejections.value(LOW_HIGH_INCOMPATIBLE)); + success = false; + } + if (vData.venousPressureLimitHigh < _venousPressureLimitHighMin || + vData.venousPressureLimitHigh > _venousPressureLimitHighMax || + vData.venousPressureLimitHigh < vData.venousPressureLimitLow) + { + emit venousPressureLimitHigh_ValidationFailed(uiRejections.value(LOW_HIGH_INCOMPATIBLE)); + success = false; + } + if (vData.bloodPressureMeasureInterval < _bloodPressureMeasureIntervalMin || + vData.bloodPressureMeasureInterval > _bloodPressureMeasureIntervalMax) + { + emit bloodPressureMeasureInterval_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + if (vData.rinsebackFlowRate < _rinsebackFlowRateMin || + vData.rinsebackFlowRate > _rinsebackFlowRateMax) + { + emit rinsebackFlowRate_ValidationFailed(uiRejections.value(OUT_OF_RANGE)); + success = false; + } + + if (!success) + { + qDebug() << "Initial treatment parameter validation failed."; + } + + + return success; + +} + +/** + * @brief VCreateTreatment::indexInItems + * Checks if the index is in the QStringList + * @param idx (int) the index + * @param items (QStringList) The list of strings to check + * @return True if it is in the list, false otherwise + */ +bool VCreateTreatment::indexInItems(quint32 idx, const QStringList &items) +{ + if (idx > (quint32)items.size() - 1) + return false; + else + return true; + +} + +/** + * @brief VCreateTreatment::onUserModifiedParameters + * Manages enabling / disabling the continue button + */ +void VCreateTreatment::onUserModifiedParameters() +{ + setTreatmentData(); + + continueEnabled(validate(treatmentData)); + emit continueEnabledChanged(continueEnabled()); + +} Index: sources/view/VCreateTreatment.h =================================================================== diff -u --- sources/view/VCreateTreatment.h (revision 0) +++ sources/view/VCreateTreatment.h (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -0,0 +1,136 @@ +#ifndef VCREATETREATMENT_H +#define VCREATETREATMENT_H + +// Qt +#include +#include +#include +#include +#include +#include + +// Project +#include "mtreatmentparameters.h" +#include "mtreatmentparametersresp.h" +#include "guicontroller.h" +#include "storageglobals.h" +#include "filesaver.h" + +using namespace Storage; + +namespace View { + +class VCreateTreatment : public QObject +{ + Q_OBJECT + +public: + explicit VCreateTreatment(QObject *parent = nullptr); + +protected: + TREATMENT_PARAMETER(quint32, bloodFlowRate, 100) // mL/min + TREATMENT_PARAMETER(quint32, dialysateFlowRate, 100) // mL/min + TREATMENT_PARAMETER(quint32, duration, 60) // minutes + TREATMENT_PARAMETER(quint32, heparinDispensingRate, 0) // mL/hr + TREATMENT_PARAMETER(quint32, heparinBolusVolume, 100) // mL + TREATMENT_PARAMETER(quint32, heparinStopTime, 1000) // mL + TREATMENT_PARAMETER(quint32, salineBolusVolume, 9999) // mL + + TREATMENT_PARAMETER(quint32, acidConcentrate, 9999) // lookup idx + TREATMENT_PARAMETER(quint32, bicarbonateConcentrate, 9999) // lookup idx + TREATMENT_PARAMETER(quint32, dialyzerType, 9999) // lookup idx + TREATMENT_PARAMETER(quint32, dialysateTemp, 35) // Celsius + TREATMENT_PARAMETER(quint32, arterialPressureLimitLow, 0) // mmHg + TREATMENT_PARAMETER(quint32, arterialPressureLimitHigh, 0) // mmHg + TREATMENT_PARAMETER(quint32, venousPressureLimitLow, 0) // mmHg + TREATMENT_PARAMETER(quint32, venousPressureLimitHigh, 0) // mmHg + TREATMENT_PARAMETER(quint32, bloodPressureMeasureInterval, 0) // minutes + TREATMENT_PARAMETER(quint32, rinsebackFlowRate, 50) // mL/min + +protected: + // ranges + PROPERTY(quint32, bloodFlowRateMin, 100) + PROPERTY(quint32, bloodFlowRateMax, 500) + PROPERTY(quint32, dialysateFlowRateMin, 100) + PROPERTY(quint32, dialysateFlowRateMax, 600) + PROPERTY(quint32, durationMin, 60) + PROPERTY(quint32, durationMax, 480) + PROPERTY(quint32, heparinDispensingRateMin, 0) + PROPERTY(quint32, heparinDispensingRateMax, 1000) + PROPERTY(quint32, heparinBolusVolumeMin, 100) + PROPERTY(quint32, heparinBolusVolumeMax, 2000) + PROPERTY(quint32, heparinStopTimeMin, 1000) + PROPERTY(quint32, heparinStopTimeMax, 2000) + PROPERTY(QStringList, salineBolusOptions, QStringList() << "100 mL" << "200 mL" << "300 mL") + PROPERTY(QStringList, acidConcentrateOptions, QStringList() << "08-1251-1" << "08-2251-0" << "08-3251-9") + PROPERTY(QStringList, bicarbonateConcentrateOptions, QStringList() << "Dimesol - BC-201") + PROPERTY(QStringList, dialyzerTypeOptions, QStringList() << "Nipro Elisio-H 17" + << "Nipro Elisio-H 19" + << "Fresenius Optiflux F160NRe" + << "Fresenius Optiflux F180NRe") + PROPERTY(quint32, dialysateTempMin, 35) + PROPERTY(quint32, dialysateTempMax, 39) + PROPERTY(qint32, arterialPressureLimitLowMin, -300) + PROPERTY(qint32, arterialPressureLimitLowMax, 200) + PROPERTY(qint32, arterialPressureLimitHighMin, -300) + PROPERTY(qint32, arterialPressureLimitHighMax, 200) + PROPERTY(qint32, venousPressureLimitLowMin, -100) + PROPERTY(qint32, venousPressureLimitLowMax, 600) + PROPERTY(qint32, venousPressureLimitHighMin, 0) + PROPERTY(qint32, venousPressureLimitHighMax, 600) + PROPERTY(quint32, bloodPressureMeasureIntervalMin, 0) + PROPERTY(quint32, bloodPressureMeasureIntervalMax, 30) + PROPERTY(quint32, rinsebackFlowRateMin, 50) + PROPERTY(quint32, rinsebackFlowRateMax, 150) + + PROPERTY(bool, continueEnabled, false) + + TreatmentData treatmentData; + bool validate(const TreatmentData &vData); + void saveNewTreatment(QJsonObject obj); + QJsonObject loadTreatmentParameterRanges(); + QStringList jsonArrayToStringList(const QJsonArray &arr); + bool indexInItems(quint32 idx, const QStringList &items); + void setTreatmentData(); + +private: + + enum UIRejectReasons { + OUT_OF_RANGE, + LOW_HIGH_INCOMPATIBLE + }; + + QHash uiRejections { + { OUT_OF_RANGE, "The selected value is out of range." }, + { LOW_HIGH_INCOMPATIBLE, "The low and high selections are incompatible." }, + + }; + + QString enumToString(GuiRequestReasons vEnum); + +private slots: + void onFinishedSaveNewTreatment(bool result); + +signals: + void didCreateTreatment(TreatmentData); + void showConfirm(); + void showPrime(); + void showBegin(); + void validateParamsWithFW(GuiActionType,QVariantList); + void resetCreateTreatment(); + void fwValidationFailed(QString reason); + +public slots: + void onResetCreateTreatment(); + void onFinishedCreate(); + void onFinishedConfirm(); + void onFinishedPrime(); + void onStart(); + void onFWValidationResponse(GuiActionType actionType, QVariantList messageData); + void onUserModifiedParameters(); + +}; + +} + +#endif // VCREATETREATMENT_H Index: sources/view/vview.h =================================================================== diff -u -r44a85c96ab55e424866ec4cca0270aa218355f82 -rc71deaab48699cffdf9db816dfac2778d79c2238 --- sources/view/vview.h (.../vview.h) (revision 44a85c96ab55e424866ec4cca0270aa218355f82) +++ sources/view/vview.h (.../vview.h) (revision c71deaab48699cffdf9db816dfac2778d79c2238) @@ -110,7 +110,8 @@ REGISTER_TYPE( VTreatmentAdjustmentFlows ) \ REGISTER_TYPE( VTreatmentAdjustmentUltrafiltrationState ) \ REGISTER_TYPE( VTreatmentAdjustmentUltrafiltrationEdit ) \ - REGISTER_TYPE( VTreatmentAdjustmentUltrafiltrationConfirm ) + REGISTER_TYPE( VTreatmentAdjustmentUltrafiltrationConfirm ) \ + REGISTER_TYPE( VCreateTreatment ) //--------------------------------------------------------------------------------//