diff --git a/CMakeLists.txt b/CMakeLists.txt index 49b2a035799476b52655d9d0aa4d0c00afd5b50a..f829e17328571c93e5cb9a0746fde8b8db0f8a1b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.15) -project(PulseExplorer VERSION 3.1.0 LANGUAGES C CXX) +project(PulseExplorer VERSION 3.2.0 LANGUAGES C CXX) include(cmake/config.cmake) diff --git a/cmake/external/External_Pulse.cmake b/cmake/external/External_Pulse.cmake index 8669f74a1e0a812372c3a07eb2f27a7838ed015d..934dd6739f865b06d0d5f36245fdae35093417be 100644 --- a/cmake/external/External_Pulse.cmake +++ b/cmake/external/External_Pulse.cmake @@ -5,12 +5,13 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/AddExternalProject.cmake) define_external_dirs_ex(Pulse) add_external_project_ex(Pulse GIT_REPOSITORY https://gitlab.kitware.com/physiology/engine.git - GIT_TAG REL_4_2_0 + GIT_TAG REL_4_3_1 CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_INSTALL_PREFIX} -DPulse_DEPENDENT_BUILD:BOOL=ON -DPulse_JAVA_API:BOOL=ON -DPulse_PYTHON_API:BOOL=ON + -DPulse_MSVC_STATIC_RUNTIME:BOOL=OFF INSTALL_COMMAND ${SKIP_STEP_COMMAND} RELATIVE_INCLUDE_PATH "" DEPENDENCIES "" diff --git a/cmake/superbuild.cmake b/cmake/superbuild.cmake index 8da6637930aefb4e8c01b0a02f1e6be5d30a03cd..d4ae2df702b7cb2ebe31135c5b8c565c6243c2cf 100644 --- a/cmake/superbuild.cmake +++ b/cmake/superbuild.cmake @@ -1,4 +1,3 @@ -include(${CMAKE_CURRENT_LIST_DIR}/config.cmake) function(define_dependency NAME) option(USE_SYSTEM_${NAME} diff --git a/src/DynamicControlsWidget.cxx b/src/DynamicControlsWidget.cxx index 4ab036e19de5342021172e134121e7a5b7cd6f06..bff5f7f9036ba555a59a864173b110a3593edcf4 100644 --- a/src/DynamicControlsWidget.cxx +++ b/src/DynamicControlsWidget.cxx @@ -12,7 +12,8 @@ See accompanying NOTICE file for details.*/ #include "controls/ActionsEditorWidget.h" #include "controls/DataRequestViewWidget.h" #include "controls/ScenarioActionsEditorWidget.h" -#include "controls/EnviornmentWidget.h" +#include "controls/EnvironmentWidget.h" +#include "controls/ModifiersWidget.h" //Showcases #include "showcases/AnaphylaxisShowcaseWidget.h" #include "showcases/MultiTraumaShowcaseWidget.h" @@ -40,7 +41,7 @@ public: delete ActionsEditor; delete DataRequestEditor; delete ScenarioActionsEditor; - delete EnviornmentEditor; + delete EnvironmentEditor; delete AnaphylaxisShowcaseWidget; delete MultiTraumaShowcaseWidget; } @@ -52,7 +53,8 @@ public: QActionsEditorWidget* ActionsEditor = nullptr; QScenarioActionsEditorWidget* ScenarioActionsEditor = nullptr; QDataRequestViewWidget* DataRequestEditor = nullptr; - QEnviornmentWidget* EnviornmentEditor = nullptr; + QEnvironmentWidget* EnvironmentEditor = nullptr; + QModifiersWidget* ModifiersEditor = nullptr; QAnaphylaxisShowcaseWidget* AnaphylaxisShowcaseWidget = nullptr; QMultiTraumaShowcaseWidget* MultiTraumaShowcaseWidget = nullptr; @@ -78,11 +80,14 @@ QDynamicControlsWidget::QDynamicControlsWidget(QPulse& qp, QWidget *parent, Qt:: m_Controls->ActionsEditor->setVisible(true); m_Controls->ActionsTab->layout()->addWidget(m_Controls->ActionsEditor); - m_Controls->DataRequestEditor = new QDataRequestViewWidget(m_Controls->Pulse, this); m_Controls->DataRequestEditor->setTitleBarWidget(new QWidget()); m_Controls->DataRequestEditor->setVisible(true); + m_Controls->ModifiersEditor = new QModifiersWidget(m_Controls->Pulse, this); + m_Controls->ModifiersEditor->setTitleBarWidget(new QWidget()); + m_Controls->ModifiersEditor->setVisible(true); + m_Controls->ScenarioActionsEditor = new QScenarioActionsEditorWidget(m_Controls->Pulse, this); m_Controls->ScenarioActionsEditor->setTitleBarWidget(new QWidget()); m_Controls->ScenarioActionsEditor->setVisible(true); @@ -91,9 +96,9 @@ QDynamicControlsWidget::QDynamicControlsWidget(QPulse& qp, QWidget *parent, Qt:: connect(m_Controls->ScenarioActionsEditor, SIGNAL(OpenAction(SEAction const&, SEScalarTime const&)), SLOT(OpenAction(SEAction const&, SEScalarTime const&))); connect(m_Controls->ActionsEditor, SIGNAL(UpdateAction(SEAction const&, SEScalarTime const&)), parentWidget(), SLOT(UpdateAction(SEAction const&, SEScalarTime const&))); - m_Controls->EnviornmentEditor = new QEnviornmentWidget(m_Controls->Pulse, this); - m_Controls->EnviornmentEditor->setTitleBarWidget(new QWidget()); - m_Controls->EnviornmentEditor->setVisible(true); + m_Controls->EnvironmentEditor = new QEnvironmentWidget(m_Controls->Pulse, this); + m_Controls->EnvironmentEditor->setTitleBarWidget(new QWidget()); + m_Controls->EnvironmentEditor->setVisible(true); QPixmap pic("resource/pulse_logo.png"); m_Controls->Icon->setPixmap(pic); @@ -123,7 +128,8 @@ QDynamicControlsWidget::~QDynamicControlsWidget() void QDynamicControlsWidget::AddTabWidgets(QTabWidget& tabWidget, int tabIdx) { tabWidget.widget(tabIdx++)->layout()->addWidget(m_Controls->DataRequestEditor); - tabWidget.widget(tabIdx++)->layout()->addWidget(m_Controls->EnviornmentEditor); + tabWidget.widget(tabIdx++)->layout()->addWidget(m_Controls->ModifiersEditor); + tabWidget.widget(tabIdx++)->layout()->addWidget(m_Controls->EnvironmentEditor); tabWidget.widget(tabIdx++)->layout()->addWidget(m_Controls->ScenarioActionsEditor); } @@ -135,7 +141,8 @@ void QDynamicControlsWidget::Clear() m_Controls->ActionsEditor->Clear(); m_Controls->DataRequestEditor->Clear(); m_Controls->ScenarioActionsEditor->Clear(); - m_Controls->EnviornmentEditor->Reset(); + m_Controls->EnvironmentEditor->Reset(); + m_Controls->ModifiersEditor->Reset(); m_Controls->ShowcaseWidget->setVisible(true); m_Controls->AnaphylaxisShowcaseWidget->setVisible(false); @@ -152,9 +159,11 @@ void QDynamicControlsWidget::Reset() m_Controls->ActionsEditor->Clear(); m_Controls->ActionsEditor->EnableInput(true); m_Controls->ActionsEditor->EnableEditControls(true); - m_Controls->EnviornmentEditor->Reset(); - m_Controls->EnviornmentEditor->EnableControls(true, false); + m_Controls->EnvironmentEditor->Reset(); + m_Controls->EnvironmentEditor->EnableControls(true, false); m_Controls->ScenarioActionsEditor->EnableControls(true); + m_Controls->ModifiersEditor->Reset(); + m_Controls->ModifiersEditor->EnableControls(false); m_Controls->DynamicControlsTab->setCurrentWidget(m_Controls->PatientTab); @@ -205,7 +214,8 @@ void QDynamicControlsWidget::SetupPulseEditor() m_Controls->ConditionsEditor->EnableInput(true); m_Controls->ActionsEditor->EnableInput(true); m_Controls->ActionsEditor->EnableEditControls(true); - m_Controls->EnviornmentEditor->EnableControls(true, false); + m_Controls->EnvironmentEditor->EnableControls(true, false); + m_Controls->ModifiersEditor->EnableControls(false); m_Controls->ScenarioActionsEditor->EnableControls(true); } @@ -384,6 +394,7 @@ void QDynamicControlsWidget::LoadScenario(SEScenario& scenario) // TODO Look for an Initial Environment Condition m_Controls->PatientEditor->EnableInput(m_Controls->ScenarioMode == ScenarioInput::Patient); m_Controls->ConditionsEditor->EnableInput(m_Controls->ScenarioMode == ScenarioInput::Patient); + // TODO Look for any active modifier actions } void QDynamicControlsWidget::SaveScenario(SEScenario& scenario) @@ -419,7 +430,8 @@ void QDynamicControlsWidget::StartEngine() m_Controls->ActionsEditor->EnableInput(false); m_Controls->ActionsEditor->EnableEditControls(false); - m_Controls->EnviornmentEditor->EnableControls(true, false); + m_Controls->EnvironmentEditor->EnableControls(true, false); + m_Controls->ModifiersEditor->EnableControls(false); m_Controls->ScenarioActionsEditor->EnableControls(false); @@ -436,7 +448,8 @@ bool QDynamicControlsWidget::SetupShowcase(QString name) m_Controls->ActionsEditor->EnableInput(false); m_Controls->ActionsEditor->EnableEditControls(false); m_Controls->ScenarioActionsEditor->EnableControls(false); - m_Controls->EnviornmentEditor->EnableControls(false, false); + m_Controls->EnvironmentEditor->EnableControls(false, false); + m_Controls->ModifiersEditor->EnableControls(false); if (name == "Anaphylaxis") { @@ -469,7 +482,8 @@ bool QDynamicControlsWidget::SetupShowcase(QString name) m_Controls->ActionsEditor->EnableInput(false); m_Controls->ActionsEditor->EnableEditControls(false); - m_Controls->EnviornmentEditor->EnableControls(true, false); + m_Controls->EnvironmentEditor->EnableControls(true, false); + m_Controls->ModifiersEditor->EnableControls(false); m_Controls->ScenarioActionsEditor->EnableControls(false); return true; @@ -481,7 +495,8 @@ void QDynamicControlsWidget::AtSteadyState(PhysiologyEngine& pulse) m_Controls->ConditionsEditor->AtSteadyState(pulse); m_Controls->ActionsEditor->AtSteadyState(pulse); m_Controls->DataRequestEditor->AtSteadyState(pulse); - m_Controls->EnviornmentEditor->AtSteadyState(pulse); + m_Controls->EnvironmentEditor->AtSteadyState(pulse); + m_Controls->ModifiersEditor->AtSteadyState(pulse); m_Controls->ScenarioActionsEditor->AtSteadyState(pulse); m_Controls->AnaphylaxisShowcaseWidget->AtSteadyState(pulse); @@ -493,7 +508,8 @@ void QDynamicControlsWidget::AtSteadyStateUpdateUI() m_Controls->ConditionsEditor->AtSteadyStateUpdateUI(); m_Controls->ActionsEditor->AtSteadyStateUpdateUI(); m_Controls->DataRequestEditor->AtSteadyStateUpdateUI(); - m_Controls->EnviornmentEditor->AtSteadyStateUpdateUI(); + m_Controls->EnvironmentEditor->AtSteadyStateUpdateUI(); + m_Controls->ModifiersEditor->AtSteadyStateUpdateUI(); m_Controls->ScenarioActionsEditor->AtSteadyStateUpdateUI(); m_Controls->AnaphylaxisShowcaseWidget->AtSteadyStateUpdateUI(); @@ -506,7 +522,8 @@ void QDynamicControlsWidget::ProcessPhysiology(PhysiologyEngine& pulse) m_Controls->ConditionsEditor->ProcessPhysiology(pulse); m_Controls->ActionsEditor->ProcessPhysiology(pulse); m_Controls->DataRequestEditor->ProcessPhysiology(pulse); - m_Controls->EnviornmentEditor->ProcessPhysiology(pulse); + m_Controls->EnvironmentEditor->ProcessPhysiology(pulse); + m_Controls->ModifiersEditor->ProcessPhysiology(pulse); m_Controls->ScenarioActionsEditor->ProcessPhysiology(pulse); m_Controls->AnaphylaxisShowcaseWidget->ProcessPhysiology(pulse); @@ -518,7 +535,8 @@ void QDynamicControlsWidget::PhysiologyUpdateUI(const std::vectorConditionsEditor->PhysiologyUpdateUI(actions); m_Controls->ActionsEditor->PhysiologyUpdateUI(actions); m_Controls->DataRequestEditor->PhysiologyUpdateUI(actions); - m_Controls->EnviornmentEditor->PhysiologyUpdateUI(actions); + m_Controls->EnvironmentEditor->PhysiologyUpdateUI(actions); + m_Controls->ModifiersEditor->PhysiologyUpdateUI(actions); m_Controls->ScenarioActionsEditor->PhysiologyUpdateUI(actions); m_Controls->AnaphylaxisShowcaseWidget->PhysiologyUpdateUI(actions); diff --git a/src/Main.cxx b/src/Main.cxx index 653192d0b60be59340de8b56b1fac4f96b77a1a9..dbf91f8858482d6a2d9cc99dd964df81986c41bb 100644 --- a/src/Main.cxx +++ b/src/Main.cxx @@ -17,7 +17,7 @@ int main(int argc, char *argv[]) QApplication::setApplicationName("Pulse Explorer"); QApplication::setOrganizationName("Kitware"); QApplication::setOrganizationDomain("kitware.com"); - QApplication::setApplicationVersion("3.0"); + QApplication::setApplicationVersion("3.2"); QApplication app(argc, argv); #ifdef Q_OS_MAC diff --git a/src/MainExplorerWindow.cxx b/src/MainExplorerWindow.cxx index ed4ce96fec8fdd1c6fe181ac535612ecc9661dcb..77a60ddd0bffb4d58fe38ccfd0b76915dd18ee86 100644 --- a/src/MainExplorerWindow.cxx +++ b/src/MainExplorerWindow.cxx @@ -118,7 +118,6 @@ MainExplorerWindow::MainExplorerWindow() // is subclassed from the UI class // i.e. m_Controls->VentilatorWidget // Hack move the ventilator widget to #2 - connect(m_Controls->VentilatorWidget, SIGNAL(UpdateAction(SEAction const&, SEScalarTime const&)), m_Controls->DynamicControls, SLOT(UpdateAction(SEAction const&, SEScalarTime const&))); int ventTab = findTab(m_Controls->TabWidget, "Ventilator"); diff --git a/src/PulseExplorerLib.cmake b/src/PulseExplorerLib.cmake index 63e9da596e85244e3a663e58503c118f47c57ac6..48000dc885b9e028921ac3b9710a06b84eca9554 100644 --- a/src/PulseExplorerLib.cmake +++ b/src/PulseExplorerLib.cmake @@ -21,10 +21,11 @@ explorer_add_library(PulseExplorerWidgets controls/ConditionsEditorWidget.h controls/DataRequestWidget.h controls/DataRequestViewWidget.h - controls/EnviornmentWidget.h + controls/EnvironmentWidget.h #controls/Icon.h controls/LabeledComboBox.h controls/LabeledDialWidget.h + controls/ModifiersWidget.h controls/NumberWidget.h #controls/Palette.h controls/PatientEditorWidget.h @@ -100,10 +101,11 @@ explorer_add_library(PulseExplorerWidgets controls/ConditionsEditorWidget.cxx controls/DataRequestViewWidget.cxx controls/DataRequestWidget.cxx - controls/EnviornmentWidget.cxx + controls/EnvironmentWidget.cxx #controls/Icon.cpp controls/LabeledComboBox.cxx controls/LabeledDialWidget.cxx + controls/ModifiersWidget.cxx controls/NumberWidget.cxx #controls/Palette.cpp controls/PatientEditorWidget.cxx @@ -178,8 +180,9 @@ explorer_add_library(PulseExplorerWidgets ui/Condition.ui ui/DataRequest.ui ui/DataRequestView.ui - ui/Enviornment.ui + ui/Environment.ui ui/LabeledDialWidget.ui + ui/Modifiers.ui ui/NumberWidget.ui ui/PatientEditor.ui ui/PlotSet.ui @@ -192,7 +195,7 @@ explorer_add_library(PulseExplorerWidgets QT_RESOURCES resources.qrc PUBLIC_LINK_LIBRARIES - Pulse::PulseEngine + Pulse::Pulse Qwt::Qwt ${QT_LIBRARIES} ) diff --git a/src/controls/AddPopup.cxx b/src/controls/AddPopup.cxx index 6d01076a8db9926fc1c51d246d543f1195fee4b3..b28a1bb991f31a80cc231ed84af00277328cde91 100644 --- a/src/controls/AddPopup.cxx +++ b/src/controls/AddPopup.cxx @@ -49,7 +49,7 @@ See accompanying NOTICE file for details.*/ #include "DataRequestsWidget.h" #include "VitalsMonitorWidget.h" #include "DynamicControlsWidget.h" -#include "EnviornmentWidget.h" +#include "EnvironmentWidget.h" #include "cdm/CommonDataModel.h" #include "PulsePhysiologyEngine.h" #include "cdm/engine/SEDataRequestManager.h" @@ -74,12 +74,12 @@ public: std::stringstream Status; double CurrentSimTime_s; InputMode Mode = InputMode::None; - QEnviornmentWidget* envir; + QEnvironmentWidget* envir; }; AddPopup::AddPopup(std::string name,QWidget *parent):QDialog(parent),Ui(new Ui::AddPopup) { - QEnviornmentWidget* envir = dynamic_cast (parent); + QEnvironmentWidget* envir = dynamic_cast (parent); m_Controls = new Controls(); m_Controls->setupUi(this); setWindowIcon(QIcon("resource/pulse.ico")); diff --git a/src/controls/DataRequestWidget.cxx b/src/controls/DataRequestWidget.cxx index b6339992f475cdceedbd6c7088f99afa95659aac..5c84ebe6aa129e2cc468290317a386498da3f7b4 100644 --- a/src/controls/DataRequestWidget.cxx +++ b/src/controls/DataRequestWidget.cxx @@ -61,6 +61,7 @@ public: //Physiology Properties std::set BloodChemistry { + "BaseExcess", "BloodDensity", "BloodPH", "BloodSpecificHeat", @@ -71,6 +72,8 @@ public: "HemoglobinContent", "OxygenSaturation", "Phosphate", + "PlasmaOsmolality", + "PlasmaOsmolarity", "PlasmaVolume", "PulseOximetry", "RedBloodCellCount", @@ -113,6 +116,7 @@ public: "MeanArterialCarbonDioxidePartialPressureDelta", "MeanCentralVenousPressure", "MeanSkinFlow", + "PeripheralPerfusionIndex", "PulmonaryArterialPressure", "PulmonaryCapillariesCoverageFraction", "PulmonaryCapillariesWedgePressure", @@ -139,6 +143,7 @@ public: "MeanBloodPressureChange", "NeuromuscularBlockLevel", "PulsePressureChange", + //"PupillaryResponse", "RespirationRateChange", "SedationLevel", "TidalVolumeChange", @@ -250,19 +255,20 @@ public: "EndTidalOxygenFraction", "EndTidalOxygenPressure", "ExpiratoryFlow", - "ExpiratoryPulmonaryResistance", + "ExpiratoryRespiratoryResistance", "ExpiratoryTidalVolume", - "FractionOfInsipredOxygen", + "ExtrinsicPositiveEndExpiratoryPressure", + "FractionOfInspiredOxygen", "HorowitzIndex", "ImposedPowerOfBreathing", "ImposedWorkOfBreathing", "InspiratoryExpiratoryRatio", "InspiratoryFlow", - "InspiratoryPulmonaryResistance", + "InspiratoryRespiratoryResistance", "InspiratoryTidalVolume", "IntrapleuralPressure", "IntrapulmonaryPressure", - "IntrinsicPositiveEndExpiredPressure", + "IntrinsicPositiveEndExpiratoryPressure", "LungCompliance", "MaximalInspiratoryPressure", "MeanAirwayPressure", @@ -273,9 +279,8 @@ public: "PeakInspiratoryPressure", "PhysiologicDeadSpace", "PhysiologicDeadSpaceTidalVolumeRatio", - "PositiveEndExpiratoryPressure", - "PulmonaryCompliance", - "PulmonaryElastance", + "RespiratoryCompliance", + "RespiratoryElastance", "RelativeTotalLungVolume", "ResistiveExpiratoryWorkOfBreathing", "ResistiveInspiratoryWorkOfBreathing", @@ -288,6 +293,7 @@ public: "TotalAlveolarVentilation", "TotalDeadSpaceVentilation", "TotalLungVolume", + "TotalPositiveEndExpiratoryPressure", "TotalPowerOfBreathing", "TotalPulmonaryVentilation", "TotalWorkOfBreathing", @@ -308,7 +314,8 @@ public: "IntracellularFluidPH", "IntracellularFluidVolume", "OxygenConsumptionRate", - "RespiratoryExchangeRatio" + "RespiratoryExchangeRatio", + "TotalFluidVolume" }; }; diff --git a/src/controls/EnviornmentWidget.cxx b/src/controls/EnvironmentWidget.cxx similarity index 94% rename from src/controls/EnviornmentWidget.cxx rename to src/controls/EnvironmentWidget.cxx index d86a08f5dff8bf7744b084092ea9f6bcf4b2b134..fd3759e20092b470d69a45b08838e65ca7b53f9e 100644 --- a/src/controls/EnviornmentWidget.cxx +++ b/src/controls/EnvironmentWidget.cxx @@ -1,14 +1,14 @@ /* Distributed under the Apache License, Version 2.0. See accompanying NOTICE file for details.*/ -#include "EnviornmentWidget.h" -#include "ui_Enviornment.h" +#include "EnvironmentWidget.h" +#include "ui_Environment.h" #include #include #include #include #include "controls/AddPopup.h" -#include "controls/EnviornmentWidget.h" +#include "controls/EnvironmentWidget.h" #include "controls/ScalarWidget.h" #include "controls/ScalarQuantityWidget.h" @@ -42,13 +42,13 @@ See accompanying NOTICE file for details.*/ #include "pulse/cdm/properties/SEScalarPower.h" #include "pulse/cdm/utils/FileUtils.h" -class QEnviornmentWidget::Controls : public Ui::EnviornmentWidget +class QEnvironmentWidget::Controls : public Ui::EnvironmentWidget { public: Controls(QPulse& qp) : Pulse(qp) {} QPulse& Pulse; - std::string type = "Enviornment"; + std::string type = "Environment"; // Environmental Conditions QScalarQuantityWidget* AirDensity; QScalarQuantityWidget* AirVelocity; @@ -97,7 +97,7 @@ public: bool AppliedFracLast = false; }; -QEnviornmentWidget::QEnviornmentWidget(QPulse& qp, QWidget *parent, Qt::WindowFlags flags) : QDockWidget(parent,flags) +QEnvironmentWidget::QEnvironmentWidget(QPulse& qp, QWidget *parent, Qt::WindowFlags flags) : QDockWidget(parent,flags) { m_Controls = new Controls(qp); m_Controls->setupUi(this); @@ -261,18 +261,18 @@ QEnviornmentWidget::QEnviornmentWidget(QPulse& qp, QWidget *parent, Qt::WindowFl connect(m_Controls->ApplyAll, SIGNAL(clicked()), this, SLOT(ControlsToEnvironment())); connect(m_Controls->LoadEnvironment, SIGNAL(clicked()), this, SLOT(LoadEnvironmentFile())); - connect(m_Controls->SaveEnviornment, SIGNAL(clicked()), this, SLOT(SaveEnvironmentFile())); + connect(m_Controls->SaveEnvironment, SIGNAL(clicked()), this, SLOT(SaveEnvironmentFile())); Reset(); } -QEnviornmentWidget::~QEnviornmentWidget() +QEnvironmentWidget::~QEnvironmentWidget() { // TODO Clean up all the widgets - m_Controls->Enviornment->close(); + m_Controls->Environment->close(); delete m_Controls; } -void QEnviornmentWidget::Reset() +void QEnvironmentWidget::Reset() { LoadEnvironmentFile(QPulse::GetDataDir().toStdString()+"/environments/Standard.json"); m_Controls->sendEnvironment = false; @@ -294,7 +294,7 @@ void QEnviornmentWidget::Reset() EnableControls(true, false); } -void QEnviornmentWidget::EnableControls(bool conditions, bool actions) +void QEnvironmentWidget::EnableControls(bool conditions, bool actions) { m_Controls->AirDensity->EnableInput(conditions); m_Controls->AirVelocity->EnableInput(conditions); @@ -314,7 +314,7 @@ void QEnviornmentWidget::EnableControls(bool conditions, bool actions) m_Controls->AmbientSmoke->EnableInput(conditions); m_Controls->LoadEnvironment->setEnabled(conditions); - m_Controls->SaveEnviornment->setEnabled(conditions); + m_Controls->SaveEnvironment->setEnabled(conditions); m_Controls->ActiveCoolingCheck->setChecked(false); m_Controls->ActiveCoolingCheck->setEnabled(actions); @@ -330,7 +330,7 @@ void QEnviornmentWidget::EnableControls(bool conditions, bool actions) m_Controls->ApplyAll->setEnabled(actions); } -void QEnviornmentWidget::LoadEnvironmentFile() +void QEnvironmentWidget::LoadEnvironmentFile() { QString fileName = QFileDialog::getOpenFileName(this, "Open Environment", QPulse::GetDataDir()+"/environments", "JSON (*.json);;Protobuf Binary (*.pbb)"); @@ -340,42 +340,42 @@ void QEnviornmentWidget::LoadEnvironmentFile() std::string s = fileName.toStdString(); LoadEnvironmentFile(s); } -void QEnviornmentWidget::LoadEnvironmentFile(const std::string& fileName) +void QEnvironmentWidget::LoadEnvironmentFile(const std::string& fileName) { if(m_Controls->ChangeEnvironmentalConditions->GetEnvironmentalConditions().SerializeFromFile(fileName, *m_Controls->SubMgr)) EnvironmentToControls(); else { QMessageBox messageBox; - std::string message = "Unable to load Enviornment File"; + std::string message = "Unable to load Environment File"; messageBox.critical(0, "Error", QString::fromUtf8(message.c_str())); messageBox.setFixedSize(500, 200); } } -void QEnviornmentWidget::SaveEnvironmentFile() +void QEnvironmentWidget::SaveEnvironmentFile() { QString fileName = QFileDialog::getSaveFileName(this, - "Save Enviornment", QPulse::GetSaveEnvironmentsDir(), "JSON (*.json);;Protobuf Binary (*.pbb)"); + "Save Environment", QPulse::GetSaveEnvironmentsDir(), "JSON (*.json);;Protobuf Binary (*.pbb)"); if (fileName.isEmpty()) return; std::string s = QPulse::AttemptRelativePath(fileName).toStdString(); - SaveEnviornmentFile(s); + SaveEnvironmentFile(s); } -void QEnviornmentWidget::SaveEnviornmentFile(const std::string& fileName) +void QEnvironmentWidget::SaveEnvironmentFile(const std::string& fileName) { ControlsToEnvironment(); if (!m_Controls->ChangeEnvironmentalConditions->GetEnvironmentalConditions().SerializeToFile(fileName) ) { QMessageBox messageBox; - std::string message = "Unable to save Enviornment File"; + std::string message = "Unable to save Environment File"; messageBox.critical(0, "Error", QString::fromUtf8(message.c_str())); messageBox.setFixedSize(500, 200); } } -void QEnviornmentWidget::ControlsToEnvironment() +void QEnvironmentWidget::ControlsToEnvironment() { m_Controls->AirDensity->GetValue(m_Controls->ChangeEnvironmentalConditions->GetEnvironmentalConditions().GetAirDensity()); m_Controls->AirVelocity->GetValue(m_Controls->ChangeEnvironmentalConditions->GetEnvironmentalConditions().GetAirVelocity()); @@ -481,7 +481,7 @@ void QEnviornmentWidget::ControlsToEnvironment() } } -void QEnviornmentWidget::EnvironmentToControls() +void QEnvironmentWidget::EnvironmentToControls() { m_Controls->AirDensity->SetValue(m_Controls->ChangeEnvironmentalConditions->GetEnvironmentalConditions().GetAirDensity()); m_Controls->AirVelocity->SetValue(m_Controls->ChangeEnvironmentalConditions->GetEnvironmentalConditions().GetAirVelocity()); @@ -533,18 +533,18 @@ void QEnviornmentWidget::EnvironmentToControls() // No need to push actions to the UI } -void QEnviornmentWidget::AtSteadyState(PhysiologyEngine& pulse) +void QEnvironmentWidget::AtSteadyState(PhysiologyEngine& pulse) { m_Controls->ChangeEnvironmentalConditions->GetEnvironmentalConditions().Copy(*pulse.GetEnvironment()->GetEnvironmentalConditions(), *m_Controls->SubMgr); } -void QEnviornmentWidget::AtSteadyStateUpdateUI() +void QEnvironmentWidget::AtSteadyStateUpdateUI() { EnvironmentToControls(); bool show = (m_Controls->Pulse.GetMode() == ExplorerMode::Editor); EnableControls(show, show); } -void QEnviornmentWidget::ProcessPhysiology(PhysiologyEngine& pulse) +void QEnvironmentWidget::ProcessPhysiology(PhysiologyEngine& pulse) {// This is called from a thread, you should NOT update UI here // This is where we pull data from pulse, and push any actions to it @@ -560,13 +560,13 @@ void QEnviornmentWidget::ProcessPhysiology(PhysiologyEngine& pulse) } } -void QEnviornmentWidget::PhysiologyUpdateUI(const std::vector& actions) +void QEnvironmentWidget::PhysiologyUpdateUI(const std::vector& actions) {// This is called from a slot, you can update UI here // Nothing is expected to be in the environment } -void QEnviornmentWidget::EnableCooling() +void QEnvironmentWidget::EnableCooling() { bool b = m_Controls->ActiveCoolingCheck->isChecked(); if (b) @@ -595,20 +595,20 @@ void QEnviornmentWidget::EnableCooling() m_Controls->CoolingFraction->setDisabled(true); } } -void QEnviornmentWidget::EnableCoolingSurfaceArea() +void QEnvironmentWidget::EnableCoolingSurfaceArea() { bool b = m_Controls->CoolingArea->GetRadioButton()->isChecked(); m_Controls->CoolingArea->EnableInput(b); m_Controls->CoolingFraction->EnableInput(!b); } -void QEnviornmentWidget::EnableCoolingSurfaceAreaFraction() +void QEnvironmentWidget::EnableCoolingSurfaceAreaFraction() { bool b = m_Controls->CoolingFraction->GetRadioButton()->isChecked(); m_Controls->CoolingArea->EnableInput(!b); m_Controls->CoolingFraction->EnableInput(b); } -void QEnviornmentWidget::EnableHeating() +void QEnvironmentWidget::EnableHeating() { bool b = m_Controls->ActiveHeatingCheck->isChecked(); if (b) @@ -637,20 +637,20 @@ void QEnviornmentWidget::EnableHeating() m_Controls->HeatingFraction->setDisabled(true); } } -void QEnviornmentWidget::EnableHeatingSurfaceArea() +void QEnvironmentWidget::EnableHeatingSurfaceArea() { bool b = m_Controls->HeatingArea->GetRadioButton()->isChecked(); m_Controls->HeatingArea->EnableInput(b); m_Controls->HeatingFraction->EnableInput(!b); } -void QEnviornmentWidget::EnableHeatingSurfaceAreaFraction() +void QEnvironmentWidget::EnableHeatingSurfaceAreaFraction() { bool b = m_Controls->HeatingFraction->GetRadioButton()->isChecked(); m_Controls->HeatingArea->EnableInput(!b); m_Controls->HeatingFraction->EnableInput(b); } -void QEnviornmentWidget::EnableAppliedTemp() +void QEnvironmentWidget::EnableAppliedTemp() { bool b = m_Controls->AppliedTempCheck->isChecked(); if (b) @@ -680,14 +680,14 @@ void QEnviornmentWidget::EnableAppliedTemp() } } -void QEnviornmentWidget::EnableAppliedTempSurfaceArea() +void QEnvironmentWidget::EnableAppliedTempSurfaceArea() { bool b = m_Controls->AppliedArea->GetRadioButton()->isChecked(); m_Controls->AppliedArea->EnableInput(b); m_Controls->AppliedFraction->EnableInput(!b); } -void QEnviornmentWidget::EnableAppliedSurfaceAreaFraction() +void QEnvironmentWidget::EnableAppliedSurfaceAreaFraction() { bool b = m_Controls->AppliedFraction->GetRadioButton()->isChecked(); m_Controls->AppliedArea->EnableInput(!b); diff --git a/src/controls/EnviornmentWidget.h b/src/controls/EnvironmentWidget.h similarity index 85% rename from src/controls/EnviornmentWidget.h rename to src/controls/EnvironmentWidget.h index 65c7b95c3c1a24f6708581814ee04b31098e78b8..edf0bb341bbac543e10bac169c0cd3eebee62e2f 100644 --- a/src/controls/EnviornmentWidget.h +++ b/src/controls/EnvironmentWidget.h @@ -9,15 +9,15 @@ See accompanying NOTICE file for details.*/ class SEEnvironmentalConditions; namespace Ui { - class EnviornmentWidget; + class EnvironmentWidget; } -class QEnviornmentWidget : public QDockWidget, public PulseListener +class QEnvironmentWidget : public QDockWidget, public PulseListener { Q_OBJECT public: - QEnviornmentWidget(QPulse& qp, QWidget *parent = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags()); - virtual ~QEnviornmentWidget(); + QEnvironmentWidget(QPulse& qp, QWidget *parent = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags()); + virtual ~QEnvironmentWidget(); void Reset(); //SECondition& GetInitialEnvironmentConditions(); @@ -44,7 +44,7 @@ protected slots: void LoadEnvironmentFile(); void LoadEnvironmentFile(const std::string& fileName); void SaveEnvironmentFile(); - void SaveEnviornmentFile(const std::string& fileName); + void SaveEnvironmentFile(const std::string& fileName); void ControlsToEnvironment(); diff --git a/src/controls/ModifiersWidget.cxx b/src/controls/ModifiersWidget.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c39d65484bfc7d457237d8ab8453f0d6e749acc8 --- /dev/null +++ b/src/controls/ModifiersWidget.cxx @@ -0,0 +1,413 @@ +/* Distributed under the Apache License, Version 2.0. +See accompanying NOTICE file for details.*/ +#include "ModifiersWidget.h" +#include "ui_Modifiers.h" +#include +#include +#include +#include + +#include "controls/AddPopup.h" +#include "controls/ModifiersWidget.h" +#include "controls/ScalarWidget.h" +#include "controls/ScalarQuantityWidget.h" + +#include "pulse/engine/PulseEngine.h" +#include "pulse/cdm/engine/SEActionManager.h" +#include "pulse/cdm/engine/SEPatientActionCollection.h" +#include "pulse/cdm/patient/actions/SECardiovascularMechanicsModification.h" +#include "pulse/cdm/system/physiology/SECardiovascularMechanicsModifiers.h" +#include "pulse/cdm/patient/actions/SERespiratoryMechanicsModification.h" +#include "pulse/cdm/system/physiology/SERespiratoryMechanicsModifiers.h" +#include "pulse/cdm/properties/SEScalarUnsigned.h" +#include "pulse/cdm/properties/SEScalarVolume.h" +#include "pulse/cdm/utils/FileUtils.h" + +class QModifiersWidget::Controls : public Ui::ModifiersWidget +{ +public: + Controls(QPulse& qp) : Pulse(qp) {} + + QPulse& Pulse; + std::string type = "Modifiers"; + // Cardiovascular Modifiers + QScalarWidget* ArterialComplianceMultiplier; + QScalarWidget* ArterialResistanceMultiplier; + QScalarWidget* PulmonaryComplianceMultiplier; + QScalarWidget* PulmonaryResistanceMultiplier; + QScalarWidget* SystemicResistanceMultiplier; + QScalarWidget* SystemicComplianceMultiplier; + QScalarWidget* VenousComplianceMultiplier; + QScalarWidget* VenousResistanceMultiplier; + QScalarWidget* HeartRateMultiplier; + QScalarWidget* StrokeVolumeMultiplier; + bool SendCardiovascularAction = false; + bool PullCardiovascularModifiers = false; + bool PushCardiovascularModifiersToControls = false; + SECardiovascularMechanicsModification* CardioModifiers; + + // Respiratory Modifiers + QScalarWidget* LeftComplianceMultiplier; + QScalarWidget* RightComplianceMultiplier; + QScalarWidget* LeftExpiratoryResistanceMultiplier; + QScalarWidget* LeftInspiratoryResistanceMultiplier; + QScalarWidget* RightExpiratoryResistanceMultiplier; + QScalarWidget* RightInspiratoryResistanceMultiplier; + QScalarWidget* UpperExpiratoryResistanceMultiplier; + QScalarWidget* UpperInspiratoryResistanceMultiplier; + QScalarWidget* RespirationRateMultiplier; + QScalarWidget* TidalVolumeMultiplier; + QScalarQuantityWidget* LeftLungVolumeIncrement; + QScalarQuantityWidget* RightLungVolumeIncrement; + bool SendRespiratoryAction = false; + bool PullRespiratoryModifiers = false; + bool PushRespiratoryModifiersToControls = false; + SERespiratoryMechanicsModification* RespModifiers; +}; + +QModifiersWidget::QModifiersWidget(QPulse& qp, QWidget *parent, Qt::WindowFlags flags) : QDockWidget(parent,flags) +{ + m_Controls = new Controls(qp); + m_Controls->setupUi(this); + + //////////////////////////////////// + // Setup Cardiovascular Modifiers // + //////////////////////////////////// + m_Controls->SendCardiovascularAction = false; + m_Controls->PullCardiovascularModifiers = false; + m_Controls->PushCardiovascularModifiersToControls = false; + m_Controls->CardioModifiers = new SECardiovascularMechanicsModification(); + + m_Controls->ArterialComplianceMultiplier = new QScalarWidget("Arterial Compliance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->ArterialComplianceMultiplier->EnableInput(false); + m_Controls->CardiovascularProperties->layout()->addWidget(m_Controls->ArterialComplianceMultiplier); + + m_Controls->ArterialResistanceMultiplier = new QScalarWidget("Arterial Resistance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->ArterialResistanceMultiplier->EnableInput(false); + m_Controls->CardiovascularProperties->layout()->addWidget(m_Controls->ArterialResistanceMultiplier); + + m_Controls->PulmonaryComplianceMultiplier = new QScalarWidget("Pulmonary Compliance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->PulmonaryComplianceMultiplier->EnableInput(false); + m_Controls->CardiovascularProperties->layout()->addWidget(m_Controls->PulmonaryComplianceMultiplier); + + m_Controls->PulmonaryResistanceMultiplier = new QScalarWidget("Pulmonary Resistance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->PulmonaryResistanceMultiplier->EnableInput(false); + m_Controls->CardiovascularProperties->layout()->addWidget(m_Controls->PulmonaryResistanceMultiplier); + + m_Controls->SystemicResistanceMultiplier = new QScalarWidget("Systemic Resistance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->SystemicResistanceMultiplier->EnableInput(false); + m_Controls->CardiovascularProperties->layout()->addWidget(m_Controls->SystemicResistanceMultiplier); + + m_Controls->SystemicComplianceMultiplier = new QScalarWidget("Systemic Compliance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->SystemicComplianceMultiplier->EnableInput(false); + m_Controls->CardiovascularProperties->layout()->addWidget(m_Controls->SystemicComplianceMultiplier); + + m_Controls->VenousComplianceMultiplier = new QScalarWidget("Venous Compliance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->VenousComplianceMultiplier->EnableInput(false); + m_Controls->CardiovascularProperties->layout()->addWidget(m_Controls->VenousComplianceMultiplier); + + m_Controls->VenousResistanceMultiplier = new QScalarWidget("Venous Resistance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->VenousResistanceMultiplier->EnableInput(false); + m_Controls->CardiovascularProperties->layout()->addWidget(m_Controls->VenousResistanceMultiplier); + + m_Controls->HeartRateMultiplier = new QScalarWidget("Heart Rate Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->HeartRateMultiplier->EnableInput(false); + m_Controls->CardiovascularProperties->layout()->addWidget(m_Controls->HeartRateMultiplier); + + m_Controls->StrokeVolumeMultiplier = new QScalarWidget("Stroke Volume Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->StrokeVolumeMultiplier->EnableInput(false); + m_Controls->CardiovascularProperties->layout()->addWidget(m_Controls->StrokeVolumeMultiplier); + + ///////////////////////////////// + // Setup Respiratory Modifiers // + ///////////////////////////////// + m_Controls->SendRespiratoryAction = false; + m_Controls->PullRespiratoryModifiers = false; + m_Controls->PushRespiratoryModifiersToControls = false; + m_Controls->RespModifiers = new SERespiratoryMechanicsModification(); + + m_Controls->LeftComplianceMultiplier = new QScalarWidget("Left Compliance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->LeftComplianceMultiplier->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->LeftComplianceMultiplier); + + m_Controls->RightComplianceMultiplier = new QScalarWidget("Right Compliance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->RightComplianceMultiplier->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->RightComplianceMultiplier); + + m_Controls->LeftExpiratoryResistanceMultiplier = new QScalarWidget("Left Expiratory Resistance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->LeftExpiratoryResistanceMultiplier->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->LeftExpiratoryResistanceMultiplier); + + m_Controls->LeftInspiratoryResistanceMultiplier = new QScalarWidget("Left Inspiratory Resistance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->LeftInspiratoryResistanceMultiplier->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->LeftInspiratoryResistanceMultiplier); + + m_Controls->RightExpiratoryResistanceMultiplier = new QScalarWidget("Right Expiratory Resistance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->RightExpiratoryResistanceMultiplier->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->RightExpiratoryResistanceMultiplier); + + m_Controls->RightInspiratoryResistanceMultiplier = new QScalarWidget("Right Inspiratory Resistance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->RightInspiratoryResistanceMultiplier->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->RightInspiratoryResistanceMultiplier); + + m_Controls->UpperExpiratoryResistanceMultiplier = new QScalarWidget("Upper Expiratory Resistance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->UpperExpiratoryResistanceMultiplier->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->UpperExpiratoryResistanceMultiplier); + + m_Controls->UpperInspiratoryResistanceMultiplier = new QScalarWidget("Upper Inspiratory Resistance Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->UpperInspiratoryResistanceMultiplier->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->UpperInspiratoryResistanceMultiplier); + + m_Controls->RespirationRateMultiplier = new QScalarWidget("Respiration Rate Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->RespirationRateMultiplier->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->RespirationRateMultiplier); + + m_Controls->TidalVolumeMultiplier = new QScalarWidget("Tidal Volume Multiplier", 1.0, 10.0, .1, ScalarOptionWidget::Check, this); + m_Controls->TidalVolumeMultiplier->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->TidalVolumeMultiplier); + + ///////////////////////////////// + // Setup Lung Volume Modifiers // + ///////////////////////////////// + + m_Controls->LeftLungVolumeIncrement = new QScalarQuantityWidget("Left Lung Volume Increment", 0.0, 100.0, 1.0, VolumeUnit::mL, ScalarOptionWidget::Check, this); + m_Controls->LeftLungVolumeIncrement->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->LeftLungVolumeIncrement); + + m_Controls->RightLungVolumeIncrement = new QScalarQuantityWidget("Right Lung Volume Increment", 0.0, 100.0, 1.0, VolumeUnit::mL, ScalarOptionWidget::Check, this); + m_Controls->RightLungVolumeIncrement->EnableInput(false); + m_Controls->RespiratoryProperties->layout()->addWidget(m_Controls->RightLungVolumeIncrement); + + + connect(m_Controls->ApplyCardiovascular, SIGNAL(clicked()), this, SLOT(CardiovascularControlsToPulse())); + connect(m_Controls->ResetCardiovascular, SIGNAL(clicked()), this, SLOT(PulseToCardiovascularControls())); + connect(m_Controls->ApplyRespiratory, SIGNAL(clicked()), this, SLOT(RespiratoryControlsToPulse())); + connect(m_Controls->ResetRespiratory, SIGNAL(clicked()), this, SLOT(PulseToRespiratoryControls())); + Reset(); +} + +QModifiersWidget::~QModifiersWidget() +{ + // TODO Clean up all the widgets + m_Controls->Modifiers->close(); + delete m_Controls; +} + +void QModifiersWidget::Reset() +{ + EnableControls(false); + PulseToCardiovascularControls(); + PulseToRespiratoryControls(); +} + +void QModifiersWidget::EnableControls(bool b) +{ + m_Controls->ArterialComplianceMultiplier->EnableInput(b,false); + m_Controls->ArterialResistanceMultiplier->EnableInput(b, false); + m_Controls->PulmonaryComplianceMultiplier->EnableInput(b, false); + m_Controls->PulmonaryResistanceMultiplier->EnableInput(b, false); + m_Controls->SystemicResistanceMultiplier->EnableInput(b, false); + m_Controls->SystemicComplianceMultiplier->EnableInput(b, false); + m_Controls->VenousComplianceMultiplier->EnableInput(b, false); + m_Controls->VenousResistanceMultiplier->EnableInput(b, false); + m_Controls->HeartRateMultiplier->EnableInput(b, false); + m_Controls->StrokeVolumeMultiplier->EnableInput(b, false); + m_Controls->ApplyCardiovascular->setEnabled(b); + m_Controls->ResetCardiovascular->setEnabled(b); + + m_Controls->LeftComplianceMultiplier->EnableInput(b, false); + m_Controls->RightComplianceMultiplier->EnableInput(b, false); + m_Controls->LeftExpiratoryResistanceMultiplier->EnableInput(b, false); + m_Controls->LeftInspiratoryResistanceMultiplier->EnableInput(b, false); + m_Controls->RightExpiratoryResistanceMultiplier->EnableInput(b, false); + m_Controls->RightInspiratoryResistanceMultiplier->EnableInput(b, false); + m_Controls->UpperExpiratoryResistanceMultiplier->EnableInput(b, false); + m_Controls->UpperInspiratoryResistanceMultiplier->EnableInput(b, false); + m_Controls->RespirationRateMultiplier->EnableInput(b, false); + m_Controls->TidalVolumeMultiplier->EnableInput(b, false); + m_Controls->LeftLungVolumeIncrement->EnableInput(b, false); + m_Controls->RightLungVolumeIncrement->EnableInput(b, false); + m_Controls->ApplyRespiratory->setEnabled(b); + m_Controls->ResetRespiratory->setEnabled(b); +} + +void QModifiersWidget::ResetControls() +{ + m_Controls->ArterialComplianceMultiplier->Reset(); + m_Controls->ArterialResistanceMultiplier->Reset(); + m_Controls->PulmonaryComplianceMultiplier->Reset(); + m_Controls->PulmonaryResistanceMultiplier->Reset(); + m_Controls->SystemicResistanceMultiplier->Reset(); + m_Controls->SystemicComplianceMultiplier->Reset(); + m_Controls->VenousComplianceMultiplier->Reset(); + m_Controls->VenousResistanceMultiplier->Reset(); + m_Controls->HeartRateMultiplier->Reset(); + m_Controls->StrokeVolumeMultiplier->Reset(); + + m_Controls->LeftComplianceMultiplier->Reset(); + m_Controls->RightComplianceMultiplier->Reset(); + m_Controls->LeftExpiratoryResistanceMultiplier->Reset(); + m_Controls->LeftInspiratoryResistanceMultiplier->Reset(); + m_Controls->RightExpiratoryResistanceMultiplier->Reset(); + m_Controls->RightInspiratoryResistanceMultiplier->Reset(); + m_Controls->UpperExpiratoryResistanceMultiplier->Reset(); + m_Controls->UpperInspiratoryResistanceMultiplier->Reset(); + m_Controls->RespirationRateMultiplier->Reset(); + m_Controls->TidalVolumeMultiplier->Reset(); + m_Controls->LeftLungVolumeIncrement->Reset(); + m_Controls->RightLungVolumeIncrement->Reset(); +} + +void QModifiersWidget::CardiovascularControlsToPulse() +{ + m_Controls->CardioModifiers->Clear(); + auto& m = m_Controls->CardioModifiers->GetModifiers(); + if (m_Controls->ArterialComplianceMultiplier->IsChecked()) + m_Controls->ArterialComplianceMultiplier->GetValue(m.GetArterialComplianceMultiplier()); + if (m_Controls->ArterialResistanceMultiplier->IsChecked()) + m_Controls->ArterialResistanceMultiplier->GetValue(m.GetArterialResistanceMultiplier()); + if (m_Controls->PulmonaryComplianceMultiplier->IsChecked()) + m_Controls->PulmonaryComplianceMultiplier->GetValue(m.GetPulmonaryComplianceMultiplier()); + if (m_Controls->PulmonaryResistanceMultiplier->IsChecked()) + m_Controls->PulmonaryResistanceMultiplier->GetValue(m.GetPulmonaryResistanceMultiplier()); + if (m_Controls->SystemicResistanceMultiplier->IsChecked()) + m_Controls->SystemicResistanceMultiplier->GetValue(m.GetSystemicResistanceMultiplier()); + if (m_Controls->SystemicComplianceMultiplier->IsChecked()) + m_Controls->SystemicComplianceMultiplier->GetValue(m.GetSystemicComplianceMultiplier()); + if (m_Controls->VenousComplianceMultiplier->IsChecked()) + m_Controls->VenousComplianceMultiplier->GetValue(m.GetVenousComplianceMultiplier()); + if (m_Controls->VenousResistanceMultiplier->IsChecked()) + m_Controls->VenousResistanceMultiplier->GetValue(m.GetVenousResistanceMultiplier()); + if (m_Controls->HeartRateMultiplier->IsChecked()) + m_Controls->HeartRateMultiplier->GetValue(m.GetHeartRateMultiplier()); + if (m_Controls->StrokeVolumeMultiplier->IsChecked()) + m_Controls->StrokeVolumeMultiplier->GetValue(m.GetStrokeVolumeMultiplier()); + + m_Controls->SendCardiovascularAction = true; +} + +void QModifiersWidget::UpdateControls(SECardiovascularMechanicsModifiers const& m) +{ + +} + +void QModifiersWidget::PulseToCardiovascularControls() +{ + m_Controls->PullCardiovascularModifiers = true; +} + +void QModifiersWidget::RespiratoryControlsToPulse() +{ + m_Controls->RespModifiers->Clear(); + auto& m = m_Controls->RespModifiers->GetModifiers(); + if (m_Controls->LeftComplianceMultiplier->IsChecked()) + m_Controls->LeftComplianceMultiplier->GetValue(m.GetLeftComplianceMultiplier()); + if (m_Controls->RightComplianceMultiplier->IsChecked()) + m_Controls->RightComplianceMultiplier->GetValue(m.GetRightComplianceMultiplier()); + if (m_Controls->LeftExpiratoryResistanceMultiplier->IsChecked()) + m_Controls->LeftExpiratoryResistanceMultiplier->GetValue(m.GetLeftExpiratoryResistanceMultiplier()); + if (m_Controls->LeftInspiratoryResistanceMultiplier->IsChecked()) + m_Controls->LeftInspiratoryResistanceMultiplier->GetValue(m.GetLeftInspiratoryResistanceMultiplier()); + if (m_Controls->RightExpiratoryResistanceMultiplier->IsChecked()) + m_Controls->RightExpiratoryResistanceMultiplier->GetValue(m.GetRightExpiratoryResistanceMultiplier()); + if (m_Controls->RightInspiratoryResistanceMultiplier->IsChecked()) + m_Controls->RightInspiratoryResistanceMultiplier->GetValue(m.GetRightInspiratoryResistanceMultiplier()); + if (m_Controls->UpperExpiratoryResistanceMultiplier->IsChecked()) + m_Controls->UpperExpiratoryResistanceMultiplier->GetValue(m.GetUpperExpiratoryResistanceMultiplier()); + if (m_Controls->UpperInspiratoryResistanceMultiplier->IsChecked()) + m_Controls->UpperInspiratoryResistanceMultiplier->GetValue(m.GetUpperInspiratoryResistanceMultiplier()); + if (m_Controls->RespirationRateMultiplier->IsChecked()) + m_Controls->RespirationRateMultiplier->GetValue(m.GetRespirationRateMultiplier()); + if (m_Controls->TidalVolumeMultiplier->IsChecked()) + m_Controls->TidalVolumeMultiplier->GetValue(m.GetTidalVolumeMultiplier()); + + if (m_Controls->LeftLungVolumeIncrement->IsChecked()) + m_Controls->LeftLungVolumeIncrement->GetValue(m.GetLungVolumeIncrement(eLungCompartment::LeftLung)); + if (m_Controls->RightLungVolumeIncrement->IsChecked()) + m_Controls->RightLungVolumeIncrement->GetValue(m.GetLungVolumeIncrement(eLungCompartment::RightLung)); + + m_Controls->SendRespiratoryAction = true; +} + +void QModifiersWidget::UpdateControls(SERespiratoryMechanicsModifiers const& m) +{ + +} + +void QModifiersWidget::PulseToRespiratoryControls() +{ + m_Controls->PullRespiratoryModifiers = true; +} + +void QModifiersWidget::AtSteadyState(PhysiologyEngine& pulse) +{ + +} +void QModifiersWidget::AtSteadyStateUpdateUI() +{ + bool show = (m_Controls->Pulse.GetMode() == ExplorerMode::Editor); + EnableControls(show); +} + +void QModifiersWidget::ProcessPhysiology(PhysiologyEngine& pulse) +{// This is called from a thread, you should NOT update UI here + // This is where we pull data from pulse, and push any actions to it + + if (m_Controls->SendCardiovascularAction) + { + m_Controls->CardioModifiers->SetIncremental(true); + pulse.ProcessAction(*m_Controls->CardioModifiers); + m_Controls->SendCardiovascularAction = false; + } + + if (m_Controls->PullCardiovascularModifiers) + { + if (pulse.GetActionManager().GetPatientActions().HasCardiovascularMechanicsModification()) + { + m_Controls->CardioModifiers->Copy( + *pulse.GetActionManager().GetPatientActions().GetCardiovascularMechanicsModification()); + } + else + { + m_Controls->CardioModifiers->Clear(); + } + m_Controls->PullCardiovascularModifiers = false; + m_Controls->PushCardiovascularModifiersToControls = true; + } + + if (m_Controls->SendRespiratoryAction) + { + m_Controls->RespModifiers->SetIncremental(true); + pulse.ProcessAction(*m_Controls->RespModifiers); + m_Controls->SendRespiratoryAction = false; + } + + if (m_Controls->PullRespiratoryModifiers) + { + if (pulse.GetActionManager().GetPatientActions().HasRespiratoryMechanicsModification()) + { + m_Controls->RespModifiers->Copy( + *pulse.GetActionManager().GetPatientActions().GetRespiratoryMechanicsModification()); + } + else + { + m_Controls->RespModifiers->Clear(); + } + m_Controls->PullRespiratoryModifiers = false; + m_Controls->PushRespiratoryModifiersToControls = true; + } +} +void QModifiersWidget::PhysiologyUpdateUI(const std::vector& actions) +{// This is called from a slot, you can update UI here + if (m_Controls->PushCardiovascularModifiersToControls) + { + UpdateControls(m_Controls->CardioModifiers->GetModifiers()); + m_Controls->PushCardiovascularModifiersToControls = false; + } + + if (m_Controls->PushRespiratoryModifiersToControls) + { + UpdateControls(m_Controls->RespModifiers->GetModifiers()); + m_Controls->PushRespiratoryModifiersToControls = false; + } +} diff --git a/src/controls/ModifiersWidget.h b/src/controls/ModifiersWidget.h new file mode 100644 index 0000000000000000000000000000000000000000..a4cac5b822434f94e174c2b73782b5164cd01029 --- /dev/null +++ b/src/controls/ModifiersWidget.h @@ -0,0 +1,47 @@ +/* Distributed under the Apache License, Version 2.0. +See accompanying NOTICE file for details.*/ +#pragma once + +#include +#include +#include "QPulse.h" + +namespace Ui { + class ModifiersWidget; +} + +class SECardiovascularMechanicsModifiers; +class SERespiratoryMechanicsModifiers; + +class QModifiersWidget : public QDockWidget, public PulseListener +{ + Q_OBJECT +public: + QModifiersWidget(QPulse& qp, QWidget *parent = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags()); + virtual ~QModifiersWidget(); + + void Reset(); + + void EnableControls(bool b); + + void UpdateControls(SECardiovascularMechanicsModifiers const& m); + void UpdateControls(SERespiratoryMechanicsModifiers const& m); + + void AtSteadyState(PhysiologyEngine& pulse) override; + void AtSteadyStateUpdateUI() override;// Main Window will call this to update UI Components + void ProcessPhysiology(PhysiologyEngine& pulse) override; + void PhysiologyUpdateUI(const std::vector& actions) override;// Main Window will call this to update UI Components + void EngineErrorUI() override {};// Main Window will call this to update UI Components + +//signals: +protected slots: + void ResetControls(); + void CardiovascularControlsToPulse(); + void PulseToCardiovascularControls(); + void RespiratoryControlsToPulse(); + void PulseToRespiratoryControls(); + +private: + class Controls; + Controls* m_Controls; +}; \ No newline at end of file diff --git a/src/controls/NumberWidget.cxx b/src/controls/NumberWidget.cxx index 56181f45bc04321a58a00b95edd5e901851ca568..1929da0b9ea4dd93a5ed3241135e2c4abf8f5005 100644 --- a/src/controls/NumberWidget.cxx +++ b/src/controls/NumberWidget.cxx @@ -17,6 +17,7 @@ struct NumberWidget::Private : public Ui::NumberWidget double actualValue = 0.0; QString name; QString unit; + bool isRatio = false; SEDataRequest* request; }; @@ -33,11 +34,12 @@ NumberWidget::~NumberWidget() delete d; } -void NumberWidget::setup(QString name, QString unit, int precision /*= 0*/) +void NumberWidget::setup(QString name, QString unit, int precision /*= 0*/, bool isRatio /*=false*/) { setName(name); setUnit(unit); setPrecision(precision); + d->isRatio = isRatio; } QString NumberWidget::getName() const @@ -69,7 +71,17 @@ double NumberWidget::getValue() const void NumberWidget::setValue(double val) { - d->value->setText(QString::number( (std::round(val * d->factor)) / d->factor , 'f', d->precision)); + if (d->isRatio) + { + val = 1 / val; + d->value->setText("1:"+QString::number((std::round(val * d->factor)) / d->factor, 'f', d->precision)); + } + else + { + d->value->setText(QString::number((std::round(val * d->factor)) / d->factor, 'f', d->precision)); + } + + d->actualValue = val; } diff --git a/src/controls/NumberWidget.h b/src/controls/NumberWidget.h index 80005086714a9e026a7297b7243a4b33190f6667..861a9dbbb1e5089ea98b078a3a63cea034908eb4 100644 --- a/src/controls/NumberWidget.h +++ b/src/controls/NumberWidget.h @@ -24,7 +24,7 @@ public: Q_PROPERTY(double value READ getValue WRITE setValue) Q_PROPERTY(int precision READ getPrecision WRITE setPrecision) - void setup(QString name, QString unit, int precision = 0); + void setup(QString name, QString unit, int precision = 0, bool isRatio=false); QString getName() const; void setName(QString name); diff --git a/src/controls/PatientEditorWidget.cxx b/src/controls/PatientEditorWidget.cxx index 9fd7f346e104fc0ee43941917fbce26ff3643117..8af212ed52c7171fd1b1fb7b3b976042733b1181 100644 --- a/src/controls/PatientEditorWidget.cxx +++ b/src/controls/PatientEditorWidget.cxx @@ -249,21 +249,25 @@ bool QPatientEditorWidget::ValidPatient() msgBox.exec(); return false; } - SEPatient p(m_Controls->Pulse.GetEngine().GetLogger()); - ControlsToPatient(p); - if (!pulse::human_adult_whole_body::SetupPatient(p)) + // Trust the state file patient + if (m_Controls->StateFilename->text().isEmpty()) { - QMessageBox msgBox(this); - msgBox.setWindowTitle("Error!"); - QString err = "Invalid Patient, check log window for more details"; - msgBox.setText(err); - msgBox.exec(); + SEPatient p(m_Controls->Pulse.GetEngine().GetLogger()); + ControlsToPatient(p); + if (!pulse::human_adult_whole_body::SetupPatient(p)) + { + QMessageBox msgBox(this); + msgBox.setWindowTitle("Error!"); + QString err = "Invalid Patient, check log window for more details"; + msgBox.setText(err); + msgBox.exec(); - // This will push all log messages to the LogBox UI - std::vector actions; - emit m_Controls->Pulse.Advanced(actions); + // This will push all log messages to the LogBox UI + std::vector actions; + emit m_Controls->Pulse.Advanced(actions); - return false; + return false; + } } return true; @@ -516,6 +520,7 @@ void QPatientEditorWidget::LoadPatientFile() msgBox.exec(); return; } + m_Controls->StateFilename->setText(""); m_Controls->Pulse.SetPatientFilename(s); PatientToControls(m_Controls->Pulse.GetPatientConfiguration().GetPatient()); } diff --git a/src/controls/PlotSetWidget.cxx b/src/controls/PlotSetWidget.cxx index bfae40cd864bc78f24ba9fb05cee6115e84145fb..04851924631af92de7ec3da07448319e8d7c16b1 100644 --- a/src/controls/PlotSetWidget.cxx +++ b/src/controls/PlotSetWidget.cxx @@ -13,26 +13,33 @@ See accompanying NOTICE file for details.*/ #include "pulse/cdm/engine/SEDataRequestManager.h" #include "pulse/cdm/properties/SEScalarTime.h" -// TODO -// I took this from SEEngineTrack, this method should go in there -// (I did change the delimeter from "-" to " ") -std::string GetTitle(SEDataRequest& dr) +// The method is used to set a plot name as well as its title +// When getting the name, we don't want the unit in the name, so includeUnit=false +// When getting the title,we want the unit, so includeUnit=true +// The Explorer DataRequest creation UI does not provide a way for the user to select a unit +// So the unit shown will be in whatever unit the engine uses for the requested property +// If we ever do provide a way for the user to select the DR unit, we will need to revisit this logic + +// TODO When we load a scenario, with data requests, do they have a unit? Are we honoring it? +std::string ToString(SEDataRequest& dr, bool includeUnit=false) { std::stringstream ss; switch (dr.GetCategory()) { case eDataRequest_Category::Patient: - ss << "Patient"; + ss << "Patient "; case eDataRequest_Category::Physiology: case eDataRequest_Category::Environment: case eDataRequest_Category::AnesthesiaMachine: case eDataRequest_Category::ECG: case eDataRequest_Category::Inhaler: { - if (!dr.GetUnit()) + if (!includeUnit) ss << dr.GetPropertyName(); - else + else if (dr.GetUnit()) ss << dr.GetPropertyName() << "(" << dr.GetUnit() << ")"; + else + ss << dr.GetPropertyName(); break; } case eDataRequest_Category::GasCompartment: @@ -42,17 +49,22 @@ std::string GetTitle(SEDataRequest& dr) { if (dr.HasSubstanceName()) { - if (!dr.GetUnit()) + if (!includeUnit) ss << dr.GetCompartmentName() << " " << dr.GetSubstanceName() << " " << dr.GetPropertyName(); + else if (dr.GetUnit()) + ss << dr.GetCompartmentName() << " " << dr.GetSubstanceName() << " " << dr.GetPropertyName() << " (" << dr.GetUnit() << ")"; else - ss << dr.GetCompartmentName() << " " << dr.GetSubstanceName() << " " << dr.GetPropertyName() << "(" << dr.GetUnit() << ")"; + ss << dr.GetCompartmentName() << " " << dr.GetSubstanceName() << " " << dr.GetPropertyName(); + } else { - if (!dr.GetUnit()) + if (!includeUnit) ss << dr.GetCompartmentName() << " " << dr.GetPropertyName(); + else if (dr.GetUnit()) + ss << dr.GetCompartmentName() << " " << dr.GetPropertyName() << " (" << dr.GetUnit() << ")"; else - ss << dr.GetCompartmentName() << " " << dr.GetPropertyName() << "(" << dr.GetUnit() << ")"; + ss << dr.GetCompartmentName() << " " << dr.GetPropertyName(); } break; } @@ -60,17 +72,21 @@ std::string GetTitle(SEDataRequest& dr) { if (dr.HasCompartmentName()) { - if (!dr.GetUnit()) + if (!includeUnit) ss << dr.GetSubstanceName() << " " << dr.GetCompartmentName() << " " << dr.GetPropertyName(); + else if (dr.GetUnit()) + ss << dr.GetSubstanceName() << " " << dr.GetCompartmentName() << " " << dr.GetPropertyName() << " (" << dr.GetUnit() << ")"; else - ss << dr.GetSubstanceName() << " " << dr.GetCompartmentName() << " " << dr.GetPropertyName() << "(" << dr.GetUnit() << ")"; + ss << dr.GetSubstanceName() << " " << dr.GetCompartmentName() << " " << dr.GetPropertyName(); } else { - if (!dr.GetUnit()) + if (!includeUnit) ss << dr.GetSubstanceName() << " " << dr.GetPropertyName(); + else if (dr.GetUnit()) + ss << dr.GetSubstanceName() << " " << dr.GetPropertyName() << " (" << dr.GetUnit() << ")"; else - ss << dr.GetSubstanceName() << " " << dr.GetPropertyName() << "(" << dr.GetUnit() << ")"; + ss << dr.GetSubstanceName() << " " << dr.GetPropertyName(); } break; } @@ -129,10 +145,10 @@ void QPlotSetWidget::Clear() void QPlotSetWidget::AddDataRequest(SEDataRequest& dr) { - QString title = GetTitle(dr).c_str(); + std::string name = ToString(dr); int idx=-1; for(; idxPlots.size(); idx++) - if (m_Controls->Plots[idx]->GetPlot().title() == title) + if (m_Controls->Plots[idx]->GetName() == name) break; if (idx == -1) { @@ -148,8 +164,10 @@ void QPlotSetWidget::AddDataRequest(SEDataRequest& dr) newPlot->GetGrid().enableY(true); m_Controls->Plots.push_back(newPlot); m_Controls->DataRequests.push_back(&dr); + newPlot->SetName(name); + // For now, use the name as the title, we'll update it with a unit later newPlot->GetPlot().setTitle(dr.GetPropertyName().c_str()); - m_Controls->PlotComboBox->addItem(title); + m_Controls->PlotComboBox->addItem(name.c_str()); m_Controls->PlotContainer->layout()->addWidget(newPlot); } // Update Controls @@ -229,7 +247,24 @@ void QPlotSetWidget::ProcessPhysiology(PhysiologyEngine& pulse) if (i+1 > m_Controls->EngineDataRequests.size()) { SEDataRequest const* dr = m_Controls->DataRequests[i]; - m_Controls->EngineDataRequests.push_back(&pulse.GetEngineTracker()->GetDataRequestManager().CopyDataRequest(*dr)); + SEDataRequest* pulseDr = &pulse.GetEngineTracker()->GetDataRequestManager().CopyDataRequest(*dr); + m_Controls->EngineDataRequests.push_back(pulseDr); + // Update the plot title to include the unit + // TrackRequest will hook up the request to the engine, + // which includes setting the unit to the engine unit if none was requested + pulse.GetEngineTracker()->TrackRequest(*pulseDr); + std::string unit = pulse.GetEngineTracker()->GetUnit(*pulseDr); + if (!unit.empty()) + { + // The name is the original string used when creating the plot + // We don't include the unit in the original name + std::string name = ToString(*pulseDr, false); + std::string title = ToString(*pulseDr, true); + for (int idx = 0; idx < m_Controls->Plots.size(); idx++) + if (m_Controls->Plots[idx]->GetName() == name) + m_Controls->Plots[idx]->GetPlot().setTitle(title.c_str()); + } + } } } diff --git a/src/controls/QwtPulsePlot.cxx b/src/controls/QwtPulsePlot.cxx index 2c9162ff60bbed8fdc0acf5e89857eb7d872f5ce..fd954b58dda3b0359f6efcb5c3e8cc32418285bc 100644 --- a/src/controls/QwtPulsePlot.cxx +++ b/src/controls/QwtPulsePlot.cxx @@ -25,6 +25,7 @@ public: double MinY; size_t MaxSize; QMutex Mutex; + std::string Name; }; QwtPulsePlot::QwtPulsePlot(QWidget* parent, size_t max_points) @@ -67,6 +68,15 @@ void QwtPulsePlot::Clear() m_Data->Values.clear(); } +std::string QwtPulsePlot::GetName() const +{ + return m_Data->Name; +} +void QwtPulsePlot::SetName(const std::string& name) +{ + m_Data->Name = name; +} + QwtPlot& QwtPulsePlot::GetPlot() { return *m_Data->Plot; } QwtPlotCurve& QwtPulsePlot::GetCurve() { return *m_Data->Curve; } QwtPlotGrid& QwtPulsePlot::GetGrid() { return *m_Data->Grid; } diff --git a/src/controls/QwtPulsePlot.h b/src/controls/QwtPulsePlot.h index bb43901c1b90f34f80603aef6f04a088d681d699..c1c0d0edfe885b3070770628f3d60b7fec926b74 100644 --- a/src/controls/QwtPulsePlot.h +++ b/src/controls/QwtPulsePlot.h @@ -22,6 +22,10 @@ public: QwtPlotCurve& GetCurve(); QwtPlotGrid& GetGrid(); + + std::string GetName() const; + void SetName(const std::string& name); + void SetDataRange(double min, double max); void Append(double time, double value); void UpdateUI(bool pad=true); diff --git a/src/controls/ScalarQuantityWidget.h b/src/controls/ScalarQuantityWidget.h index 62a9dd226da32d30f89206ed1fbaf1bdabe22f1e..d3c514d770541eab8c86a2ec7a8e07f034c51f6f 100644 --- a/src/controls/ScalarQuantityWidget.h +++ b/src/controls/ScalarQuantityWidget.h @@ -30,11 +30,13 @@ public: void AddUnit(const Unit& unit); void SetValue(const SEScalarQuantity& s); void GetValue(SEScalarQuantity& s); + bool SetDefault(double d);// Assumed to be in default units, must be in range void EnableInput(bool b); void EnableInput(bool check, bool value); void EnableConverter(bool b); void FullDisable(); void FullEnable(); + bool IsZero() const; const QRadioButton* GetRadioButton() { return m_Radio; } @@ -57,6 +59,7 @@ protected slots: double m_Max; double m_Step; double m_LastValue; + double m_Default; int m_LastUnitIndex; const Unit& m_DefaultUnit; std::vector m_Units; diff --git a/src/controls/ScalarQuantityWidget.inl b/src/controls/ScalarQuantityWidget.inl index f97f73e42c0ddaa2b6efdb35d9d0ed726ed3ff25..3c0df2267a25fd326d707be5af6a61ed815bf6ef 100644 --- a/src/controls/ScalarQuantityWidget.inl +++ b/src/controls/ScalarQuantityWidget.inl @@ -70,6 +70,7 @@ QScalarQuantityWidget::QScalarQuantityWidget(const QString& name, double m m_Value->setMaximumSize(QSize(70, 22)); m_Value->setDecimals(2); m_Layout->addWidget(m_Value); + m_Default = min; m_Unit = new QComboBox(this); QSizePolicy sizePolicyU(QSizePolicy::Fixed, QSizePolicy::Maximum); @@ -109,7 +110,7 @@ void QScalarQuantityWidget::Reset() m_Radio->setChecked(false); EnableInput(true, false); m_LastUnitIndex = 0; - m_LastValue = m_Value->minimum(); + m_LastValue = m_Default; m_Unit->setCurrentIndex(m_LastUnitIndex); m_Value->setValue(m_LastValue); } @@ -140,6 +141,17 @@ void QScalarQuantityWidget::AddUnit(const Unit& unit) m_Unit->addItem(QString::fromStdString(unit.GetString())); } +template +bool QScalarQuantityWidget::SetDefault(double d) // Assumed to be in default units +{ + if (d >= m_Value->minimum() && d <= m_Value->maximum()) + { + m_Default = d; + return true; + } + return false; +} + template void QScalarQuantityWidget::SetValue(const SEScalarQuantity& s) { @@ -175,6 +187,12 @@ void QScalarQuantityWidget::GetValue(SEScalarQuantity& s) s.SetValue(m_Value->value(),*m_Units[m_Unit->currentIndex()]); } +template +bool QScalarQuantityWidget::IsZero() const +{ + return SEScalar::IsZero(m_Value->value(), ZERO_APPROX); +} + template void QScalarQuantityWidget::EnableInput(bool b) { @@ -184,7 +202,11 @@ template void QScalarQuantityWidget::EnableInput(bool check, bool value) { if (m_Check != nullptr) + { m_Check->setEnabled(check); + if (!value) + m_Check->setChecked(false); + } if (m_Radio != nullptr) m_Radio->setChecked(check); m_Value->setEnabled(value); diff --git a/src/controls/ScalarWidget.cxx b/src/controls/ScalarWidget.cxx index bd613e1660bcd50635a969c75765ab97c67c316e..54ea03c85268ef39352e42374e644456915aaa86 100644 --- a/src/controls/ScalarWidget.cxx +++ b/src/controls/ScalarWidget.cxx @@ -145,7 +145,11 @@ void QScalarWidget::EnableInput(bool b) void QScalarWidget::EnableInput(bool check, bool value) { if (m_Check != nullptr) + { m_Check->setEnabled(check); + if (!value) + m_Check->setChecked(false); + } if (m_Radio != nullptr) m_Radio->setChecked(check); m_Value->setEnabled(value); diff --git a/src/controls/VentilatorWidget.cxx b/src/controls/VentilatorWidget.cxx index 05e867f66d789954740c02b82e2a6df7d88c67b5..46b132333ef7c171bfe76350e5b078cd732b5712 100644 --- a/src/controls/VentilatorWidget.cxx +++ b/src/controls/VentilatorWidget.cxx @@ -1,16 +1,20 @@ /* Distributed under the Apache License, Version 2.0. See accompanying NOTICE file for details.*/ + #include "VentilatorWidget.h" #include "ui_Ventilator.h" #include #include +#include "pulse/cdm/engine/SEActionManager.h" #include "pulse/cdm/engine/SEDataRequestManager.h" #include "pulse/cdm/engine/SEEngineTracker.h" +#include "pulse/cdm/engine/SEEquipmentActionCollection.h" #include "pulse/cdm/properties/SEScalar0To1.h" #include "pulse/cdm/properties/SEScalarFrequency.h" #include "pulse/cdm/properties/SEScalarPressure.h" +#include "pulse/cdm/properties/SEScalarMassPerVolume.h" #include "pulse/cdm/properties/SEScalarTime.h" #include "pulse/cdm/properties/SEScalarVolume.h" #include "pulse/cdm/properties/SEScalarVolumePerPressure.h" @@ -25,21 +29,20 @@ #include "pulse/cdm/system/physiology/SERespiratorySystem.h" #include "pulse/engine/PulseEngine.h" - #include "QwtPulsePlot.h" #include "LabeledComboBox.h" #include "NumberWidget.h" #include "QMutex" #include "VentilatorHysteresisWidget.h" - - +#include "controls/ScalarWidget.h" +#include "controls/ScalarQuantityWidget.h" struct QVentilatorWidget::Private : public Ui::VentilatorWidget { Private(QVentilatorWidget* parent) : parent(parent) { setupUi(parent); - setupInitialValues(); + SetupInitialValues(); hysteresis = new QVentilatorHysteresisWidget(parent, Qt::WindowType::Window); hysteresis->hide(); connect(hysteresisButton, &QPushButton::released, [this]() @@ -49,77 +52,160 @@ struct QVentilatorWidget::Private : public Ui::VentilatorWidget }); } + const SESubstanceManager* subMgr; + // Mode QVector dials; QVector numbers; LabeledDialWidget* slopeWidget = nullptr; LabeledDialWidget* tiWidget = nullptr; QVentilatorWidget* parent = nullptr; QVentilatorHysteresisWidget* hysteresis = nullptr; + // Triggers + QScalarQuantityWidget* inspirationPatientTriggerFlow; + QScalarQuantityWidget* inspirationPatientTriggerPressure; + QWidget* modelTrigger; + QRadioButton* modelRadio; + QLabel* modelTriggerLabel; + QSpacerItem* modelTriggerSpacer; + QLabel* modelTriggerValue; + QHBoxLayout* modelTriggerLayout; + // Drugs + QScalarQuantityWidget* albuterolConcentration; + const SESubstance* albuterol = nullptr; + QScalarWidget* desfluraneVolumeFraction; + const SESubstance* desflurane = nullptr; static const int PC = 0; static const int VC = 1; static const int CPAP = 2; struct ActionSet { - SEMechanicalVentilatorPressureControl pc; - SEMechanicalVentilatorVolumeControl vc; + SEMechanicalVentilatorPressureControl pc_ac; + SEMechanicalVentilatorPressureControl pc_cmv; + SEMechanicalVentilatorVolumeControl vc_ac; + SEMechanicalVentilatorVolumeControl vc_cmv; SEMechanicalVentilatorContinuousPositiveAirwayPressure cpap; }; ActionSet initialValues; ActionSet currentValues; - std::vector> actions; + // These are used when loading a state and updating the UI at steady state + const SEMechanicalVentilatorMode* stateMode = nullptr; + const SEMechanicalVentilatorHold* stateHold = nullptr; + SEMechanicalVentilatorSettings* stateSettings = nullptr; + // For passing setting updates over to the engine as we run + std::vector> unique_ptr_actions; + // More detailed configuration properties to append to the selected mode int modeFromAction = -1; QMutex actionMutex; - void addAction(std::unique_ptr p) + void Reset() + { + for (auto number : numbers) + { + number->setValue(0); + } + + modeBox->setCurrentIndex(0); + + for (auto dial : dials) + { + dial->hide(); + } + + plot_0->clear(); + plot_0->setYRange(-0.1, 20.); + min_0->setText("0"); + max_0->setText("20"); + plot_0->setMaxPoints(50 * 15); // 15 Seconds + plot_0->setScaleMode(PulsePainterPlot::ScaleMode::Expanding); + plot_0->setUpdateMode(PulsePainterPlot::UpdateMode::InPlace); + plot_1->clear(); + plot_1->setYRange(-30, 30); + min_1->setText("-30"); + max_1->setText("30"); + plot_1->setMaxPoints(50 * 15); // 15 Seconds + plot_1->setScaleMode(PulsePainterPlot::ScaleMode::Expanding); + plot_1->setUpdateMode(PulsePainterPlot::UpdateMode::InPlace); + plot_2->clear(); + plot_2->setYRange(-100.0, 500); + plot_2->setMaxPoints(50 * 15); // 15 Seconds + plot_2->setScaleMode(PulsePainterPlot::ScaleMode::Expanding); + plot_2->setUpdateMode(PulsePainterPlot::UpdateMode::InPlace); + min_2->setText("-100"); + max_2->setText("500"); + + currentValues.pc_ac.Copy(initialValues.pc_ac, *subMgr); + currentValues.pc_cmv.Copy(initialValues.pc_cmv, *subMgr); + currentValues.vc_ac.Copy(initialValues.vc_ac, *subMgr); + currentValues.vc_cmv.Copy(initialValues.vc_cmv, *subMgr); + currentValues.cpap.Copy(initialValues.cpap, *subMgr); + + EnableTriggers(false); + EnableDrugs(false); + } + + void ResetDials() + { + SetMode(modeBox->currentText(), true); + } + + void AddAction(std::unique_ptr p) { QMutexLocker lock(&actionMutex); - actions.push_back(std::move(p)); + unique_ptr_actions.push_back(std::move(p)); } - void applyActions(PhysiologyEngine& pulse) + void ApplyActions(PhysiologyEngine& pulse) { QMutexLocker lock(&actionMutex); - for (auto& action : actions) + for (auto& action : unique_ptr_actions) { pulse.ProcessAction(*action); } - actions.clear(); + unique_ptr_actions.clear(); } - void setupInitialValues() - { + void SetupInitialValues() + { // Try to keep this in sync with whats in the Pulse HowTo_MechanicalVentilator.cpp { - auto& action = initialValues.pc; - action.SetConnection(eSwitch::On); - action.GetFractionInspiredOxygen().SetValue(.21); - action.GetInspiratoryPressure().SetValue(13.0, PressureUnit::cmH2O); - action.GetInspiratoryPeriod().SetValue(1.0, TimeUnit::s); - action.GetRespirationRate().SetValue(12, FrequencyUnit::Per_min); - action.GetPositiveEndExpiredPressure().SetValue(5.0, PressureUnit::cmH2O); - action.GetSlope().SetValue(0.2, TimeUnit::s); + auto& pc_cmv = initialValues.pc_cmv; + pc_cmv.SetConnection(eSwitch::On); + pc_cmv.GetFractionInspiredOxygen().SetValue(.21); + pc_cmv.GetInspiratoryPressure().SetValue(23.0, PressureUnit::cmH2O); + pc_cmv.GetInspiratoryPeriod().SetValue(1.1, TimeUnit::s); + pc_cmv.GetRespirationRate().SetValue(12, FrequencyUnit::Per_min); + pc_cmv.GetPositiveEndExpiratoryPressure().SetValue(5.0, PressureUnit::cmH2O); + pc_cmv.GetSlope().SetValue(0.2, TimeUnit::s); + auto& pc_ac = initialValues.pc_ac; + pc_ac.Copy(pc_cmv, *subMgr); + pc_ac.SetMode(eMechanicalVentilator_PressureControlMode::AssistedControl); + pc_cmv.SetMode(eMechanicalVentilator_PressureControlMode::ContinuousMandatoryVentilation); } { - auto& action = initialValues.vc; - action.SetConnection(eSwitch::On); - action.GetFractionInspiredOxygen().SetValue(0.21); - action.GetTidalVolume().SetValue(600, VolumeUnit::mL); - action.GetInspiratoryPeriod().SetValue(1.0, TimeUnit::s); - action.GetRespirationRate().SetValue(12, FrequencyUnit::Per_min); - action.GetPositiveEndExpiredPressure().SetValue(5.0, PressureUnit::cmH2O); - action.GetFlow().SetValue(50, VolumePerTimeUnit::L_Per_min); + auto& vc_cmv = initialValues.vc_cmv; + vc_cmv.SetConnection(eSwitch::On); + vc_cmv.GetFractionInspiredOxygen().SetValue(0.21); + vc_cmv.GetTidalVolume().SetValue(540, VolumeUnit::mL); + vc_cmv.GetInspiratoryPeriod().SetValue(1.0, TimeUnit::s); + vc_cmv.GetRespirationRate().SetValue(12, FrequencyUnit::Per_min); + vc_cmv.GetPositiveEndExpiratoryPressure().SetValue(5.0, PressureUnit::cmH2O); + vc_cmv.GetFlow().SetValue(60, VolumePerTimeUnit::L_Per_min); auto& pc_ac = initialValues.pc_ac; + auto& vc_ac = initialValues.vc_ac; + vc_ac.Copy(vc_cmv, *subMgr); + vc_ac.SetMode(eMechanicalVentilator_VolumeControlMode::AssistedControl); + vc_cmv.SetMode(eMechanicalVentilator_VolumeControlMode::ContinuousMandatoryVentilation); } { - auto& action = initialValues.cpap; - action.SetConnection(eSwitch::On); - action.GetFractionInspiredOxygen().SetValue(0.21); - action.GetPositiveEndExpiredPressure().SetValue(5.0, PressureUnit::cmH2O); - action.GetDeltaPressureSupport().SetValue(8, PressureUnit::cmH2O); - action.GetSlope().SetValue(0.2, TimeUnit::s); + auto& cpap = initialValues.cpap; + cpap.SetConnection(eSwitch::On); + cpap.GetFractionInspiredOxygen().SetValue(0.21); + cpap.GetPositiveEndExpiratoryPressure().SetValue(5.0, PressureUnit::cmH2O); + cpap.GetDeltaPressureSupport().SetValue(10, PressureUnit::cmH2O); + cpap.GetSlope().SetValue(0.2, TimeUnit::s); } } @@ -133,23 +219,25 @@ struct QVentilatorWidget::Private : public Ui::VentilatorWidget Hold }; - void clearSlope() + void ClearSlope() { if (tiWidget == nullptr) return; - disconnect(tiWidget, &LabeledDialWidget::valueChanged, parent, &QVentilatorWidget::updateSlope); + disconnect(tiWidget, &LabeledDialWidget::valueChanged, parent, &QVentilatorWidget::UpdateSlope); tiWidget = nullptr; slopeWidget = nullptr; } - void setupSlope(LabeledDialWidget* ti, LabeledDialWidget* slope) + // The range of the slope is dependent on another widgets range, set up and connect the two + void SetupSlope(LabeledDialWidget* ti, LabeledDialWidget* slope) { - clearSlope(); + ClearSlope(); slopeWidget = slope; tiWidget = ti; - connect(tiWidget, &LabeledDialWidget::valueChanged, parent, &QVentilatorWidget::updateSlope); + connect(tiWidget, &LabeledDialWidget::valueChanged, parent, &QVentilatorWidget::UpdateSlope); } - void showDials(int maxIndex) + // maxIndex the index of the last dial to show, dials with index higher will be hidden in the UI + void ShowDials(int maxIndex) { for (int i = 0; i < maxIndex && i < dials.size(); ++i) { @@ -157,10 +245,9 @@ struct QVentilatorWidget::Private : public Ui::VentilatorWidget } } - - void setMode(QString mode, bool resetValues = false) + void SetMode(QString mode, bool resetValues = false) { - clearSlope(); + ClearSlope(); for (auto dial : dials) { @@ -169,136 +256,291 @@ struct QVentilatorWidget::Private : public Ui::VentilatorWidget if (mode == "NONE") { - setUIState(VentilatorNone); + SetUIState(VentilatorNone); return; } - else if (mode == "PC" || mode == "PC-CMV" || mode == "PC-AC") - { - if (resetValues) currentValues.pc.Copy(initialValues.pc); - auto& action = currentValues.pc; - dial_0->setup("FiO2", "",0.21, 1.0, 100, 0.1, &action.GetFractionInspiredOxygen()); - dial_1->setup("Pinsp", "cmH2O", 1, 100, 1, 1, &action.GetInspiratoryPressure()); - dial_2->setup("Ti", "s", 0.1, 60, 10, 0.1, &action.GetInspiratoryPeriod()); - dial_3->setup("RR", "bpm", 10, 60, 1, 1.0, &action.GetRespirationRate()); - dial_4->setup("PEEP", "cmH2O", 0, 50, 1, 1.0, &action.GetPositiveEndExpiredPressure()); - dial_5->setup("Slope", "s", 0, dial_2->getValue(), 10, 0.1, &action.GetSlope()); - setupSlope(dial_2, dial_5); - showDials(6); - } - else if (mode == "VC" || mode == "VC-CMV" || mode == "VC-AC") - { - if (resetValues) currentValues.vc.Copy(initialValues.vc); - auto& action = currentValues.vc; - dial_0->setup("FiO2", "", 0.21, 1.0, 100, 0.1, &action.GetFractionInspiredOxygen()); - dial_1->setup("VT", "mL", 100, 2000, 1, 1.0, &action.GetTidalVolume()); - dial_2->setup("Ti", "s", 0.1, 60, 10, 0.1, &action.GetInspiratoryPeriod()); - dial_3->setup("RR", "bpm", 10, 60, 1, 1.0, &action.GetRespirationRate()); - dial_4->setup("PEEP", "cmH2O", 0, 50, 1, 1.0, &action.GetPositiveEndExpiredPressure()); - dial_5->setup("Flow", "L/min", 1, 100, 1, 1.0, &action.GetFlow()); - showDials(6); + else if (mode == "PC-CMV" || mode == "PC-AC") + { + SEMechanicalVentilatorPressureControl* initial; + SEMechanicalVentilatorPressureControl* current; + if (mode == "PC-AC") + { + EnableTriggers(true); + initial = &initialValues.pc_ac; + current = ¤tValues.pc_ac; + } + else + { + EnableTriggers(false); + initial = &initialValues.pc_cmv; + current = ¤tValues.pc_cmv; + } + if (resetValues) + current->Copy(*initial, *subMgr); + + dial_0->setup("FiO2", "",0.21, 1.0, 100, 0.01, ¤t->GetFractionInspiredOxygen()); + dial_1->setup("Pinsp", "cmH2O", 1, 100, 1, 1, ¤t->GetInspiratoryPressure()); + dial_2->setup("Ti", "s", 0.1, 60, 10, 0.1, ¤t->GetInspiratoryPeriod()); + dial_3->setup("RR", "bpm", 10, 60, 1, 1.0, ¤t->GetRespirationRate()); + dial_4->setup("PEEP", "cmH2O", 0, 50, 1, 1.0, ¤t->GetPositiveEndExpiratoryPressure()); + dial_5->setup("Slope", "s", 0, dial_2->getValue(), 10, 0.1, ¤t->GetSlope()); + SetupSlope(dial_2, dial_5); + ShowDials(6); + if (mode == "PC-AC") + { + // Update Trigger + if (current->HasInspirationPatientTriggerFlow()) + { + EnableFlowTrigger(); + inspirationPatientTriggerFlow->SetValue(current->GetInspirationPatientTriggerFlow()); + } + else if (current->HasInspirationPatientTriggerPressure()) + { + EnablePressureTrigger(); + inspirationPatientTriggerPressure->SetValue(current->GetInspirationPatientTriggerPressure()); + } + else + { + EnableModelTrigger(); + } + } + } + else if (mode == "VC-CMV" || mode == "VC-AC") + { + SEMechanicalVentilatorVolumeControl* initial; + SEMechanicalVentilatorVolumeControl* current; + if (mode == "VC-AC") + { + EnableTriggers(true); + initial = &initialValues.vc_ac; + current = ¤tValues.vc_ac; + } + else + { + EnableTriggers(false); + initial = &initialValues.vc_cmv; + current = ¤tValues.vc_cmv; + } + if (resetValues) + current->Copy(*initial, *subMgr); + dial_0->setup("FiO2", "", 0.21, 1.0, 100, 0.01, ¤t->GetFractionInspiredOxygen()); + dial_1->setup("VT", "mL", 100, 2000, 1, 10.0, ¤t->GetTidalVolume()); + dial_2->setup("Ti", "s", 0.1, 60, 10, 0.1, ¤t->GetInspiratoryPeriod()); + dial_3->setup("RR", "bpm", 10, 60, 1, 1.0, ¤t->GetRespirationRate()); + dial_4->setup("PEEP", "cmH2O", 0, 50, 1, 1.0, ¤t->GetPositiveEndExpiratoryPressure()); + dial_5->setup("Flow", "L/min", 1, 100, 1, 1.0, ¤t->GetFlow()); + ShowDials(6); + if (mode == "VC-AC") + { + // Update Trigger + if (current->HasInspirationPatientTriggerFlow()) + { + EnableFlowTrigger(); + inspirationPatientTriggerFlow->SetValue(current->GetInspirationPatientTriggerFlow()); + } + else if (current->HasInspirationPatientTriggerPressure()) + { + EnablePressureTrigger(); + inspirationPatientTriggerPressure->SetValue(current->GetInspirationPatientTriggerPressure()); + } + else + { + EnableModelTrigger(); + } + } } else if (mode == "CPAP") { - if (resetValues) currentValues.cpap.Copy(initialValues.cpap); - auto& action = currentValues.cpap; - dial_0->setup("FiO2", "", 0.21, 1.0, 100, 0.1, &action.GetFractionInspiredOxygen()); - dial_1->setup("PEEP", "cmH2O", 0, 50, 1, 1.0, &action.GetPositiveEndExpiredPressure()); - dial_2->setup("deltaPsupp", "cmH2O", 1, 100, 1, 1.0, &action.GetDeltaPressureSupport()); - dial_3->setup("Slope", "s", 0, 1, 100, 0.1, &action.GetSlope()); - showDials(4); + EnableTriggers(true); + if (resetValues) currentValues.cpap.Copy(initialValues.cpap, *subMgr); + auto& cpap = currentValues.cpap; + dial_0->setup("FiO2", "", 0.21, 1.0, 100, 0.01, &cpap.GetFractionInspiredOxygen()); + dial_1->setup("PEEP", "cmH2O", 0, 50, 1, 1.0, &cpap.GetPositiveEndExpiratoryPressure()); + dial_2->setup("deltaPsupp", "cmH2O", 1, 100, 1, 1.0, &cpap.GetDeltaPressureSupport()); + dial_3->setup("Slope", "s", 0, 1, 100, 0.1, &cpap.GetSlope()); + ShowDials(4); + // Update Trigger + if (cpap.HasInspirationPatientTriggerFlow()) + { + EnableFlowTrigger(); + inspirationPatientTriggerFlow->SetValue(cpap.GetInspirationPatientTriggerFlow()); + } + else if (cpap.HasInspirationPatientTriggerPressure()) + { + EnablePressureTrigger(); + inspirationPatientTriggerPressure->SetValue(cpap.GetInspirationPatientTriggerPressure()); + } + else + { + EnableModelTrigger(); + } } else { qWarning() << "Mode " << mode << " not found."; } - setUIState((applyButton->text() == "Connect") ? Disconnected : Connected); + applyButton->setEnabled(true); + SetUIState((applyButton->text() == "Connect") ? Disconnected : Connected); } - void setUIState(UIState state) + void SetUIState(UIState state) { switch (state) { case Default: - reset(); - setUIState(Off); - break; - case Off: - modeBox->setEnabled(false); + Reset(); + SetUIState(Off); applyButton->setEnabled(false); - holdButton->setEnabled(false); - disconnectButton->setEnabled(false); break; case Enabled: modeBox->setEnabled(true); - setUIState((applyButton->text() == "Connect") ? Disconnected : Connected); + resetButton->setEnabled(true); + SetUIState((applyButton->text() == "Connect") ? Disconnected : Connected); break; + case Off: case VentilatorNone: - modeBox->setEnabled(true); - applyButton->setEnabled(false); + if (state == Off) + { + modeBox->setEnabled(false); + applyButton->setEnabled(false); + } + else if (state == VentilatorNone) + { + modeBox->setEnabled(true); + } + resetButton->setEnabled(true); holdButton->setEnabled(false); disconnectButton->setEnabled(false); + resetButton->setEnabled(false); + hysteresisButton->setEnabled(false); + // Triggers + EnableTriggers(false); + // Drugs + EnableDrugs(false); break; case Connected: - applyButton->setText("Apply"); - applyButton->setEnabled(true); - holdButton->setEnabled(true); - disconnectButton->setEnabled(true); - break; case Disconnected: - applyButton->setText("Connect"); - applyButton->setEnabled(true); - holdButton->setDisabled(true); - disconnectButton->setDisabled(true); + if (state == Connected) + { + applyButton->setText("Apply"); + disconnectButton->setEnabled(true); + EnableDrugs(true); + } + else if (state == Disconnected) + { + applyButton->setText("Connect"); + disconnectButton->setEnabled(false); + EnableDrugs(false); + } + resetButton->setEnabled(true); + holdButton->setEnabled(true); + hysteresisButton->setEnabled(true); break; } } - void reset() + void EnableTriggers(bool b) { - for (auto number : numbers) + if (b && modelTrigger->isEnabled()) + return; // We are already enabled + if (!b && !modelTrigger->isEnabled()) + return // We are already disabled + + inspirationPatientTriggerFlow->Reset(); + inspirationPatientTriggerPressure->Reset(); + inspirationPatientTriggerFlow->EnableInput(false, false); + inspirationPatientTriggerPressure->EnableInput(false, false); + + if (!b) { - number->setValue(0); + inspirationPatientTriggerFlow->FullDisable(); + inspirationPatientTriggerPressure->FullDisable(); + modelTrigger->setEnabled(false); + apply_triggers->setEnabled(false); + modelRadio->setChecked(false); + modelTriggerValue->setText("N/A"); } + else + { + inspirationPatientTriggerFlow->FullEnable(); + inspirationPatientTriggerFlow->EnableInput(false); + inspirationPatientTriggerPressure->FullEnable(); + inspirationPatientTriggerPressure->EnableInput(false); + modelTrigger->setEnabled(true); + modelRadio->setChecked(true); + apply_triggers->setEnabled(true); + modelTriggerValue->setText("On"); + } + } + void EnableFlowTrigger() + { + inspirationPatientTriggerFlow->EnableInput(true); + inspirationPatientTriggerPressure->EnableInput(false); + modelRadio->setChecked(false); + modelTriggerValue->setEnabled(false); - modeBox->setCurrentIndex(0); - + } + void EnablePressureTrigger() + { + inspirationPatientTriggerFlow->EnableInput(false); + inspirationPatientTriggerPressure->EnableInput(true); + modelRadio->setChecked(false); + modelTriggerValue->setEnabled(false); + } + void EnableModelTrigger() + { + inspirationPatientTriggerFlow->EnableInput(false); + inspirationPatientTriggerPressure->EnableInput(false); + modelRadio->setChecked(true); + modelTriggerValue->setEnabled(true); + } - for (auto dial : dials) + void PullTrigger(SEScalarVolumePerTime& flowTrigger, SEScalarPressure& pressureTrigger) + { + // Pull from Triggers Tab + if (apply_triggers->isEnabled()) { - dial->hide(); + if (inspirationPatientTriggerFlow->IsChecked()) + { + pressureTrigger.Invalidate(); + inspirationPatientTriggerFlow->GetValue(flowTrigger); + if (flowTrigger.IsZero()) + flowTrigger.Invalidate(); + if (!flowTrigger.IsValid()) + { + // Default back to model trigger + inspirationPatientTriggerFlow->EnableInput(true, false); + EnableModelTrigger(); + } + } + else if (inspirationPatientTriggerPressure->IsChecked()) + { + flowTrigger.Invalidate(); + inspirationPatientTriggerPressure->GetValue(pressureTrigger); + if (pressureTrigger.IsZero()) + pressureTrigger.Invalidate(); + if (!pressureTrigger.IsValid()) + { + // Default back to model trigger + inspirationPatientTriggerPressure->EnableInput(true, false); + EnableModelTrigger(); + } + } + else + { + flowTrigger.Invalidate(); + pressureTrigger.Invalidate(); + EnableModelTrigger(); + } } - - plot_0->clear(); - plot_0->setYRange(-0.1, 20.); - min_0->setText("0"); - max_0->setText("20"); - plot_0->setMaxPoints(50 * 15); // 15 Seconds - plot_0->setScaleMode(PulsePainterPlot::ScaleMode::Expanding); - plot_0->setUpdateMode(PulsePainterPlot::UpdateMode::InPlace); - plot_1->clear(); - plot_1->setYRange(-30, 30); - min_1->setText("-30"); - max_1->setText("30"); - plot_1->setMaxPoints(50 * 15); // 15 Seconds - plot_1->setScaleMode(PulsePainterPlot::ScaleMode::Expanding); - plot_1->setUpdateMode(PulsePainterPlot::UpdateMode::InPlace); - plot_2->clear(); - plot_2->setYRange(-100.0, 500); - plot_2->setMaxPoints(50 * 15); // 15 Seconds - plot_2->setScaleMode(PulsePainterPlot::ScaleMode::Expanding); - plot_2->setUpdateMode(PulsePainterPlot::UpdateMode::InPlace); - min_2->setText("-100"); - max_2->setText("500"); - - currentValues.pc.Copy(initialValues.pc); - currentValues.vc.Copy(initialValues.vc); - currentValues.cpap.Copy(initialValues.cpap); } - void resetDials() + void EnableDrugs(bool b) { - setMode(modeBox->currentText(), true); + albuterolConcentration->setEnabled(b); + desfluraneVolumeFraction->setEnabled(b); + apply_drugs->setEnabled(b); } }; @@ -320,15 +562,66 @@ QVentilatorWidget::QVentilatorWidget(QWidget *parent, Qt::WindowFlags flags) : d->number_5, d->number_6, d->number_7 }; - setupNumbers(); - - connect(d->modeBox, &QComboBox::currentTextChanged, this, &QVentilatorWidget::setMode); - - connect(d->applyButton, &QPushButton::clicked, this, &QVentilatorWidget::applyAction); - connect(d->disconnectButton, &QPushButton::clicked, this, &QVentilatorWidget::disconnectAction); - connect(d->holdButton, &QPushButton::pressed, this, &QVentilatorWidget::addHold); - connect(d->holdButton, &QPushButton::released, this, &QVentilatorWidget::removeHold); - connect(d->resetButton, &QPushButton::released, this, &QVentilatorWidget::resetDials); + SetupNumbers(); + + // Mode Controls + connect(d->modeBox, &QComboBox::currentTextChanged, this, &QVentilatorWidget::SetMode); + connect(d->applyButton, &QPushButton::clicked, this, &QVentilatorWidget::ApplyAction); + connect(d->disconnectButton, &QPushButton::clicked, this, &QVentilatorWidget::DisconnectAction); + connect(d->holdButton, &QPushButton::pressed, this, &QVentilatorWidget::AddHold); + connect(d->holdButton, &QPushButton::released, this, &QVentilatorWidget::RemoveHold); + connect(d->resetButton, &QPushButton::released, this, &QVentilatorWidget::ResetDials); + // Triggers + d->inspirationPatientTriggerFlow = new QScalarQuantityWidget("Flow", 0, 10000, 1, VolumePerTimeUnit::L_Per_min, ScalarOptionWidget::Radio, this); + d->inspirationPatientTriggerFlow->AddUnit(VolumePerTimeUnit::L_Per_s); + d->inspirationPatientTriggerFlow->AddUnit(VolumePerTimeUnit::mL_Per_s); + d->inspirationPatientTriggerFlow->AddUnit(VolumePerTimeUnit::mL_Per_min); + d->inspirationPatientTriggerFlow->SetDefault(2); + d->inspirationPatientTriggerFlow->EnableInput(false, false); + d->trigger_layout->layout()->addWidget(d->inspirationPatientTriggerFlow); + d->inspirationPatientTriggerPressure = new QScalarQuantityWidget("Pressure", -10000, 10000, 1, PressureUnit::cmH2O, ScalarOptionWidget::Radio, this); + d->inspirationPatientTriggerPressure->AddUnit(PressureUnit::mmHg); + d->inspirationPatientTriggerPressure->AddUnit(PressureUnit::Pa); + d->inspirationPatientTriggerPressure->AddUnit(PressureUnit::psi); + d->inspirationPatientTriggerPressure->SetDefault(1); + d->inspirationPatientTriggerPressure->EnableInput(false, false); + d->trigger_layout->layout()->addWidget(d->inspirationPatientTriggerPressure); + d->modelTriggerLayout = new QHBoxLayout(); + d->modelTriggerLayout->setSpacing(6); + d->modelTriggerLayout->setContentsMargins(-1, 3, -1, 3); + QSizePolicy SsizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + SsizePolicy.setHorizontalStretch(0); + SsizePolicy.setVerticalStretch(0); + d->modelRadio = new QRadioButton(this); + d->modelTriggerLayout->addWidget(d->modelRadio); + d->modelTriggerLabel = new QLabel("Respiratory Model", this); + SsizePolicy.setHeightForWidth(d->modelTriggerLabel->sizePolicy().hasHeightForWidth()); + d->modelTriggerLabel->setSizePolicy(SsizePolicy); + d->modelTriggerLayout->addWidget(d->modelTriggerLabel); + d->modelTriggerSpacer = new QSpacerItem(40, 30, QSizePolicy::Expanding, QSizePolicy::Maximum); + d->modelTriggerLayout->addItem(d->modelTriggerSpacer); + d->modelTriggerValue = new QLabel("On", this); + d->modelTriggerLayout->addWidget(d->modelTriggerValue); + d->modelTrigger = new QWidget(this); + d->modelTrigger->setLayout(d->modelTriggerLayout); + d->trigger_layout->layout()->addWidget(d->modelTrigger); + connect(d->inspirationPatientTriggerFlow->GetRadioButton(), SIGNAL(clicked()), this, SLOT(EnableFlowTrigger())); + connect(d->inspirationPatientTriggerPressure->GetRadioButton(), SIGNAL(clicked()), this, SLOT(EnablePressureTrigger())); + connect(d->modelRadio, SIGNAL(clicked()), this, SLOT(EnableModelTrigger())); + connect(d->apply_triggers, &QPushButton::clicked, this, &QVentilatorWidget::ApplyTriggers); + // Drugs + d->albuterolConcentration = new QScalarQuantityWidget("Albuterol\nConcentration", 0, 10000, 1, MassPerVolumeUnit::g_Per_L, ScalarOptionWidget::Check, this); + d->albuterolConcentration->AddUnit(MassPerVolumeUnit::g_Per_dL); + d->albuterolConcentration->AddUnit(MassPerVolumeUnit::g_Per_mL); + d->albuterolConcentration->AddUnit(MassPerVolumeUnit::mg_Per_L); + d->albuterolConcentration->AddUnit(MassPerVolumeUnit::mg_Per_dL); + d->albuterolConcentration->AddUnit(MassPerVolumeUnit::mg_Per_mL); + d->albuterolConcentration->AddUnit(MassPerVolumeUnit::ug_Per_L); + d->albuterolConcentration->AddUnit(MassPerVolumeUnit::ug_Per_mL); + d->drugs_layout->layout()->addWidget(d->albuterolConcentration); + d->desfluraneVolumeFraction = new QScalarWidget("Desflurane\nVolume Fraction", 0, 1, 0.05, ScalarOptionWidget::Check, this); + d->drugs_layout->layout()->addWidget(d->desfluraneVolumeFraction); + connect(d->apply_drugs, &QPushButton::clicked, this, &QVentilatorWidget::ApplyDrugs); Reset(); } @@ -340,46 +633,91 @@ QVentilatorWidget::~QVentilatorWidget() void QVentilatorWidget::Reset() { - d->setUIState(QVentilatorWidget::Private::Default); + d->SetUIState(QVentilatorWidget::Private::Default); + d->EnableTriggers(false); + d->EnableDrugs(false); } void QVentilatorWidget::AtSteadyState(PhysiologyEngine& pulse) { - // Create Data Requests here ... - - auto& dm = pulse.GetEngineTracker()->GetDataRequestManager(); - - // PulsePhysiology Name, Unit, UI Abbreviation - // HS would like to set up things this way but that still has a few issues -// static std::vector> items = -// { -// {"PeakInspiratoryPressure", PressureUnit::cmH2O, "PIP"}, -// {"MeanAirwayPressure", PressureUnit::cmH2O, "Pmean"}, -// {"RespirationRate", FrequencyUnit::Per_min, "RR"}, -// {"TidalVolume", VolumeUnit::mL, "VT"}, -// {"TotalPulmonaryVentilation", VolumePerTimeUnit::L_Per_min, "MVe"}, -// {"EndTidalCarbonDioxidePressure", PressureUnit::mmHg, "etCO2"}, -// {"PulmonaryCompliance", {}, "cDyn"}, -// }; + // Called when we load a state too, so copy any data or actions + d->subMgr = &pulse.GetSubstanceManager(); + d->albuterol = d->subMgr->GetSubstance("Albuterol"); + d->desflurane = d->subMgr->GetSubstance("Desflurane"); + + if (pulse.GetActionManager().GetEquipmentActions().HasMechanicalVentilatorContinuousPositiveAirwayPressure()) + { + d->stateMode = pulse.GetActionManager().GetEquipmentActions().GetMechanicalVentilatorContinuousPositiveAirwayPressure(); + } + else if (pulse.GetActionManager().GetEquipmentActions().HasMechanicalVentilatorPressureControl()) + { + d->stateMode = pulse.GetActionManager().GetEquipmentActions().GetMechanicalVentilatorPressureControl(); + } + else if (pulse.GetActionManager().GetEquipmentActions().HasMechanicalVentilatorVolumeControl()) + { + d->stateMode = pulse.GetActionManager().GetEquipmentActions().GetMechanicalVentilatorVolumeControl(); + } + + if (pulse.GetActionManager().GetEquipmentActions().HasMechanicalVentilatorHold()) + { + d->stateHold = pulse.GetActionManager().GetEquipmentActions().GetMechanicalVentilatorHold(); + // TODO Log("Removing the hold from the loaded state"); + } + + d->stateSettings = const_cast(pulse.GetMechanicalVentilator()->GetSettings()); + + d->hysteresis->AtSteadyState(pulse); + +// PulsePhysiology Name, Unit, UI Abbreviation +// HS would like to set up things this way but that still has a few issues +// auto& dm = pulse.GetEngineTracker()->GetDataRequestManager(); +// static std::vector> items = +// { +// {"PeakInspiratoryPressure", PressureUnit::cmH2O, "PIP"}, +// {"MeanAirwayPressure", PressureUnit::cmH2O, "Pmean"}, +// {"RespirationRate", FrequencyUnit::Per_min, "RR"}, +// {"TidalVolume", VolumeUnit::mL, "VT"}, +// {"TotalPulmonaryVentilation", VolumePerTimeUnit::L_Per_min, "MVe"}, +// {"EndTidalCarbonDioxidePressure", PressureUnit::mmHg, "etCO2"}, +// {"PulmonaryCompliance", {}, "cDyn"}, +// }; // -// int i = 0; -// for (auto& item : items) -// { -// const std::string& physName = std::get<0>(item); -// const CCompoundUnit& unit = std::get<1>(item); -// const QString& label = std::get<2>(item); +// int i = 0; +// for (auto& item : items) +// { +// const std::string& physName = std::get<0>(item); +// const CCompoundUnit& unit = std::get<1>(item); +// const QString& label = std::get<2>(item); // -// if (physName.empty()) continue; +// if (physName.empty()) continue; // -// d->numbers[i]->setDataRequest(&dm.CreatePhysiologyDataRequest(physName, unit)); +// d->numbers[i]->setDataRequest(&dm.CreatePhysiologyDataRequest(physName, unit)); // -// d->numbers[i]->setName(label); -// d->numbers[i]->setUnit(QString(unit.GetString().c_str())); -// ++i; -// } - d->hysteresis->AtSteadyState(pulse); +// d->numbers[i]->setName(label); +// d->numbers[i]->setUnit(QString(unit.GetString().c_str())); +// ++i; +// } + } +void QVentilatorWidget::AtSteadyStateUpdateUI() +{ + if (d->stateMode) + { + d->SetUIState(Private::Connected); + UpdateModeUI(); + } + if (d->stateHold) + {// Just force the hold release, this would be a wierd edge case to support + // The use can just enable the hold manually + RemoveHold(); + } + d->hysteresis->AtSteadyStateUpdateUI(); + if (d->stateSettings) + UpdateSettingsUI(); +} + + void QVentilatorWidget::ProcessPhysiology(PhysiologyEngine& pulse) { // This is called from a thread, you should NOT update UI here @@ -395,7 +733,7 @@ void QVentilatorWidget::ProcessPhysiology(PhysiologyEngine& pulse) d->number_3->setWithoutUpdate(ventilator->GetTotalPulmonaryVentilation(VolumePerTimeUnit::L_Per_min)); d->number_4->setWithoutUpdate(ventilator->GetRespirationRate(FrequencyUnit::Per_min)); d->number_5->setWithoutUpdate(ventilator->GetEndTidalCarbonDioxidePressure(PressureUnit::mmHg)); - d->number_6->setWithoutUpdate(ventilator->GetDynamicPulmonaryCompliance(VolumePerPressureUnit::L_Per_cmH2O)); + d->number_6->setWithoutUpdate(ventilator->GetStaticRespiratoryCompliance(VolumePerPressureUnit::mL_Per_cmH2O)); d->number_7->setWithoutUpdate(ventilator->GetInspiratoryExpiratoryRatio()); double time_s = pulse.GetSimulationTime(TimeUnit::s); @@ -403,53 +741,31 @@ void QVentilatorWidget::ProcessPhysiology(PhysiologyEngine& pulse) d->plot_1->append(time_s, ventilator->GetInspiratoryFlow(VolumePerTimeUnit::L_Per_min)); d->plot_2->append(time_s, ventilator->GetTotalLungVolume(VolumeUnit::mL)); - d->applyActions(pulse); -} - -void QVentilatorWidget::AtSteadyStateUpdateUI() -{ - d->hysteresis->AtSteadyStateUpdateUI(); - + d->ApplyActions(pulse); } void QVentilatorWidget::PhysiologyUpdateUI(const std::vector& actions) { - // This is called from a slot, you can update UI here - // This is where we take the pulse data we pulled and push it to a UI widget for (auto number : d->numbers) { number->updateValue(); } - - // Only the last/newest action in the set is relevant - auto itEnd = actions.crend(); - auto it = actions.crbegin(); - while (it != itEnd) + // This is where we take the pulse data we pulled and push it to a UI widget + for (const SEAction* a : actions) { - if (auto typedAction = dynamic_cast(*it)) + if (auto mode = dynamic_cast(a)) { - d->currentValues.pc.Copy(*typedAction); - QString currentText = (typedAction->GetMode() == eMechanicalVentilator_PressureControlMode::AssistedControl) ? - "PC-AC" : "PC-CMV"; - d->modeBox->setCurrentText(currentText); - break; + d->stateMode = mode; + UpdateModeUI(); } - if (auto typedAction = dynamic_cast(*it)) + else if (auto cfg = dynamic_cast(a)) { - d->currentValues.vc.Copy(*typedAction); - QString currentText = (typedAction->GetMode() == eMechanicalVentilator_VolumeControlMode::AssistedControl) ? - "VC-AC" : "VC-CMV"; - d->modeBox->setCurrentText("VC-CMV"); - break; - } - if (auto typedAction = dynamic_cast(*it)) - { - d->currentValues.cpap.Copy(*typedAction); - d->modeBox->setCurrentText("CPAP"); - break; + // TODO NO SUPPORT FOR FILE BASED SETTINGS YET + d->stateSettings = const_cast(cfg->GetSettings()); + UpdateSettingsUI(); } - ++it; } + d->hysteresis->PhysiologyUpdateUI(actions); // update plot axis labels { @@ -467,10 +783,97 @@ void QVentilatorWidget::PhysiologyUpdateUI(const std::vector& a d->min_2->setText(QString::number(range.first, 'f', 0)); d->max_2->setText(QString::number(range.second, 'f', 0)); } +} - d->hysteresis->PhysiologyUpdateUI(actions); +void QVentilatorWidget::UpdateModeUI() +{ + if (!d->stateMode) + return; + + if (auto typedAction = dynamic_cast(d->stateMode)) + { + if (typedAction->GetMode() == eMechanicalVentilator_PressureControlMode::AssistedControl) + { + d->currentValues.pc_ac.Copy(*typedAction, *d->subMgr); + d->modeBox->setCurrentText("PC-AC");// Triggers SetMode (which updates dial values) + } + else + { + d->currentValues.pc_cmv.Copy(*typedAction, *d->subMgr); + d->modeBox->setCurrentText("PC-CMV");// Triggers SetMode (which updates dial values) + } + } + else if (auto typedAction = dynamic_cast(d->stateMode)) + { + if (typedAction->GetMode() == eMechanicalVentilator_VolumeControlMode::AssistedControl) + { + d->currentValues.vc_ac.Copy(*typedAction, *d->subMgr); + d->modeBox->setCurrentText("VC-AC");// Triggers SetMode (which updates dial values) + } + else + { + d->currentValues.vc_cmv.Copy(*typedAction, *d->subMgr); + d->modeBox->setCurrentText("VC-CMV");// Triggers SetMode (which updates dial values) + } + } + else if (auto typedAction = dynamic_cast(d->stateMode)) + { + d->currentValues.cpap.Copy(*typedAction, *d->subMgr); + d->modeBox->setCurrentText("CPAP");// Triggers SetMode (which updates dial values) + } + d->stateMode = nullptr; +} + +void QVentilatorWidget::UpdateSettingsUI() +{ + std::string mode = d->modeBox->currentText().toStdString(); + + if (mode == "NONE") + { + d->EnableDrugs(false); + return; + } + + // Update Drugs + d->EnableDrugs(true); + if (d->stateSettings->HasConcentrationInspiredAerosol(*d->albuterol)) + { + SEScalarMassPerVolume& c = d->stateSettings->GetConcentrationInspiredAerosol(*d->albuterol).GetConcentration(); + if (c.IsZero()) + { + d->albuterolConcentration->EnableInput(true, false); + } + else + { + d->albuterolConcentration->SetValue(c); + } + } + else + { + d->albuterolConcentration->EnableInput(true, false); + } + + if (d->stateSettings->HasFractionInspiredGas(*d->desflurane)) + { + SEScalar0To1& a = d->stateSettings->GetFractionInspiredGas(*d->desflurane).GetFractionAmount(); + if (a.IsZero()) + { + d->desfluraneVolumeFraction->EnableInput(true, false); + } + else + { + d->desfluraneVolumeFraction->SetValue(a); + } + } + else + { + d->desfluraneVolumeFraction->EnableInput(true, false); + } + d->stateSettings = nullptr; } + + void QVentilatorWidget::EngineErrorUI() { @@ -478,15 +881,15 @@ void QVentilatorWidget::EngineErrorUI() void QVentilatorWidget::StartEngine() { - d->setUIState(QVentilatorWidget::Private::VentilatorNone); + d->SetUIState(QVentilatorWidget::Private::VentilatorNone); } -void QVentilatorWidget::updateSlope(double value) +void QVentilatorWidget::UpdateSlope(double value) { d->slopeWidget->setMaximumValue(value); } -void QVentilatorWidget::applyAction() +void QVentilatorWidget::ApplyAction() { QString mode = d->modeBox->currentText(); SEScalarTime t; @@ -494,72 +897,76 @@ void QVentilatorWidget::applyAction() if (mode == "NONE") { + DisconnectAction(); return; } else if (mode == "PC-CMV" || mode == "PC-AC") { auto action = std::make_unique(); - action->Copy(d->currentValues.pc); - action->SetConnection(eSwitch::On); if (mode == "PC-AC") { - action->SetMode(eMechanicalVentilator_PressureControlMode::AssistedControl); + d->PullTrigger(d->currentValues.pc_ac.GetInspirationPatientTriggerFlow(), + d->currentValues.pc_ac.GetInspirationPatientTriggerPressure()); + PullSupplementalSettings(d->currentValues.pc_ac.GetSupplementalSettings()); + action->Copy(d->currentValues.pc_ac, *d->subMgr); } else { - action->SetMode(eMechanicalVentilator_PressureControlMode::ContinuousMandatoryVentilation); + PullSupplementalSettings(d->currentValues.pc_cmv.GetSupplementalSettings()); + action->Copy(d->currentValues.pc_cmv, *d->subMgr); } emit(UpdateAction(*action, t)); - d->addAction(std::move(action)); + d->AddAction(std::move(action)); } else if (mode == "VC-CMV" || mode == "VC-AC") { auto action = std::make_unique(); - action->Copy(d->currentValues.vc); - action->SetConnection(eSwitch::On); - // See setMode for dial assignments + + // See SetMode for dial assignments if (mode == "VC-AC") { - action->SetMode(eMechanicalVentilator_VolumeControlMode::AssistedControl); + d->PullTrigger(d->currentValues.vc_ac.GetInspirationPatientTriggerFlow(), + d->currentValues.vc_ac.GetInspirationPatientTriggerPressure()); + PullSupplementalSettings(d->currentValues.vc_ac.GetSupplementalSettings()); + action->Copy(d->currentValues.vc_ac, *d->subMgr); } else { - action->SetMode(eMechanicalVentilator_VolumeControlMode::ContinuousMandatoryVentilation); + PullSupplementalSettings(d->currentValues.vc_cmv.GetSupplementalSettings()); + action->Copy(d->currentValues.vc_cmv, *d->subMgr); } emit(UpdateAction(*action, t)); - - d->addAction(std::move(action)); + d->AddAction(std::move(action)); } else if (mode == "CPAP") { auto action = std::make_unique(); - action->SetConnection(eSwitch::On); - action->Copy(d->currentValues.cpap); + d->PullTrigger(d->currentValues.cpap.GetInspirationPatientTriggerFlow(), + d->currentValues.cpap.GetInspirationPatientTriggerPressure()); + PullSupplementalSettings(d->currentValues.cpap.GetSupplementalSettings()); + action->Copy(d->currentValues.cpap, *d->subMgr); emit(UpdateAction(*action, t)); - - d->addAction(std::move(action)); + d->AddAction(std::move(action)); } else { qWarning() << "Mode " << mode << " not found."; } - - d->setUIState(Private::Connected); - + d->SetUIState(Private::Connected); } -void QVentilatorWidget::disconnectAction() +void QVentilatorWidget::DisconnectAction() { auto action = std::make_unique(); action->GetSettings().SetConnection(eSwitch::Off); SEScalarTime t; t.Invalidate(); emit(UpdateAction(*action, t)); - d->addAction(std::move(action)); + d->AddAction(std::move(action)); - d->setUIState(Private::Disconnected); + d->SetUIState(Private::Disconnected); } -void QVentilatorWidget::addHold() +void QVentilatorWidget::AddHold() { /// If the hold button is enabled /// both of these other buttons are enabled as well, therefore @@ -569,48 +976,112 @@ void QVentilatorWidget::addHold() auto action = std::make_unique(); action->SetState(eSwitch::On); - d->addAction(std::move(action)); + d->AddAction(std::move(action)); } -void QVentilatorWidget::removeHold() +void QVentilatorWidget::RemoveHold() { d->applyButton->setDisabled(false); d->disconnectButton->setDisabled(false); auto action = std::make_unique(); action->SetState(eSwitch::Off); - d->addAction(std::move(action)); + d->AddAction(std::move(action)); + d->stateHold = nullptr; } -void QVentilatorWidget::setMode(QString val) +void QVentilatorWidget::SetMode(QString val) { - d->setMode(val); + d->SetMode(val); } -void QVentilatorWidget::resetDials() +void QVentilatorWidget::ResetDials() { - d->resetDials(); + d->ResetDials(); } -void QVentilatorWidget::setupNumbers() +void QVentilatorWidget::SetupNumbers() { d->number_0->setup("PIP", "cmH20"); d->number_1->setup("VT", "mL"); d->number_2->setup("Pmean", "cmH20"); d->number_3->setup("MVe", "L/min"); d->number_4->setup("RR", "/min"); - d->number_5->setup("etCO2", "mmHg"); // , 2 - d->number_6->setup("cDyn", "L/cmH2O", 2); - d->number_7->setup("I:E", "", 2); + d->number_5->setup("etCO2", "mmHg"); + d->number_6->setup("cStat", "mL/cmH2O"); + d->number_7->setup("I:E", "", 1, true); } -void QVentilatorWidget::lockForHold() +void QVentilatorWidget::LockForHold() { d->applyButton->setDisabled(true); } -void QVentilatorWidget::unlock() +void QVentilatorWidget::Unlock() { d->applyButton->setDisabled(false); } + +void QVentilatorWidget::EnableFlowTrigger() +{ + d->EnableFlowTrigger(); + +} +void QVentilatorWidget::EnablePressureTrigger() +{ + d->EnablePressureTrigger(); +} +void QVentilatorWidget::EnableModelTrigger() +{ + d->EnableModelTrigger(); +} + +void QVentilatorWidget::ApplyTriggers() +{ + ApplyAction(); +} + +void QVentilatorWidget::ApplyDrugs() +{ + ApplyAction(); +} + +void QVentilatorWidget::PullSupplementalSettings(SEMechanicalVentilatorSettings& settings) +{ + settings.Clear(); + // Pull from Drugs Tab + if (d->albuterolConcentration->IsChecked()) + { + d->albuterolConcentration->GetValue( + settings.GetConcentrationInspiredAerosol(*d->albuterol).GetConcentration() + ); + if (!settings.GetConcentrationInspiredAerosol(*d->albuterol).GetConcentration().IsValid()) + settings.GetConcentrationInspiredAerosol(*d->albuterol).GetConcentration().SetValue(0, MassPerVolumeUnit::g_Per_L); + if (settings.GetConcentrationInspiredAerosol(*d->albuterol).GetConcentration().IsZero()) + { + d->albuterolConcentration->EnableInput(true, false); + } + } + else + { + settings.GetConcentrationInspiredAerosol(*d->albuterol).GetConcentration().SetValue(0, MassPerVolumeUnit::g_Per_L); + } + + if (d->desfluraneVolumeFraction->IsChecked()) + { + d->desfluraneVolumeFraction->GetValue( + settings.GetFractionInspiredGas(*d->desflurane).GetFractionAmount() + ); + if (!settings.GetFractionInspiredGas(*d->desflurane).GetFractionAmount().IsValid()) + settings.GetFractionInspiredGas(*d->desflurane).GetFractionAmount().SetValue(0); + if (settings.GetFractionInspiredGas(*d->desflurane).GetFractionAmount().IsZero()) + { + d->desfluraneVolumeFraction->EnableInput(true, false); + } + } + else + { + settings.GetFractionInspiredGas(*d->desflurane).GetFractionAmount().SetValue(0); + } +} diff --git a/src/controls/VentilatorWidget.h b/src/controls/VentilatorWidget.h index d487ef1947f251ffaaf28b09ae669d9906ecb639..ca63c20e7ca515bf22a915f3626f874c1e0c72ea 100644 --- a/src/controls/VentilatorWidget.h +++ b/src/controls/VentilatorWidget.h @@ -4,6 +4,7 @@ #include #include "QPulse.h" +class SEMechanicalVentilatorSettings; namespace Ui { class VentilatorWidget; @@ -34,43 +35,40 @@ signals: protected slots: /// Used to update the slope widget with a new range - void updateSlope(double value); + void UpdateSlope(double value); /// On apply take the current mode and input parameters and /// apply an action to pulse - void applyAction(); + void ApplyAction(); /// Disconnect the ventilator - void disconnectAction(); + void DisconnectAction(); ///@{ /// Handle holds - void addHold(); - void removeHold(); + void AddHold(); + void RemoveHold(); ///@} - void setMode(QString val); - void resetDials(); + void SetMode(QString val); + void ResetDials(); -protected: - ///@{ - /// The range of the slope is dependent on another widgets range, set up and connect - /// the two - void setupSlope(LabeledDialWidget* tiWidget, LabeledDialWidget* slopeWidget); - void clearSlope(); - ///@} + void EnableFlowTrigger(); + void EnablePressureTrigger(); + void EnableModelTrigger(); + void ApplyTriggers(); + void ApplyDrugs(); - /// Display a number of dials - /// \param maxIndex the index of the last dial to show, dials with index higher - /// will be hidden in the UI - void showDials(int maxIndex); - - void setupNumbers(); +protected: + void SetupNumbers(); + void UpdateModeUI(); + void UpdateSettingsUI(); + void PullSupplementalSettings(SEMechanicalVentilatorSettings& ss); ///@{ /// When hold is clicked, the UI should be locked for input - void lockForHold(); - void unlock(); + void LockForHold(); + void Unlock(); private: struct Private; diff --git a/src/controls/actions/DyspneaWidget.cxx b/src/controls/actions/DyspneaWidget.cxx index 5fc92baee3f5b67e569d75e6d76c1395e770a95e..09abdfb04dff5757612bb9ee053f828d5f32e932 100644 --- a/src/controls/actions/DyspneaWidget.cxx +++ b/src/controls/actions/DyspneaWidget.cxx @@ -14,14 +14,17 @@ public: Controls(QPulse& qp) : Pulse(qp) {} QPulse& Pulse; SEDyspnea Action; - QScalarWidget* Severity; + QScalarWidget* RespirationRateSeverity; + QScalarWidget* TidalVolumeSeverity; }; QDyspneaWidget::QDyspneaWidget(QPulse& qp, QWidget *parent, Qt::WindowFlags flags) : QActionWidget(qp, parent, flags) { m_Controls = new Controls(qp); - m_Controls->Severity = new QScalarWidget("Severity", 0, 1, 0.1, ScalarOptionWidget::None, this); - Properties()->layout()->addWidget(m_Controls->Severity); + m_Controls->RespirationRateSeverity = new QScalarWidget("RespirationRateSeverity", 0, 1, 0.1, ScalarOptionWidget::None, this); + Properties()->layout()->addWidget(m_Controls->RespirationRateSeverity); + m_Controls->TidalVolumeSeverity = new QScalarWidget("TidalVolumeSeverity", 0, 1, 0.1, ScalarOptionWidget::None, this); + Properties()->layout()->addWidget(m_Controls->TidalVolumeSeverity); Properties()->layout()->addWidget(GetProcessTimeCtrl()); Reset(); } @@ -35,7 +38,8 @@ void QDyspneaWidget::Reset() { QActionWidget::Reset(); m_Controls->Action.Clear(); - m_Controls->Severity->Reset(); + m_Controls->RespirationRateSeverity->Reset(); + m_Controls->TidalVolumeSeverity->Reset(); } SEAction& QDyspneaWidget::GetAction() @@ -50,13 +54,15 @@ const SEAction& QDyspneaWidget::GetAction() const void QDyspneaWidget::SetEnabled(bool b) { QActionWidget::SetEnabled(b); - m_Controls->Severity->EnableInput(b); + m_Controls->RespirationRateSeverity->EnableInput(b); + m_Controls->TidalVolumeSeverity->EnableInput(b); } void QDyspneaWidget::ControlsToAction() { QActionWidget::ControlsToAction(); - m_Controls->Severity->GetValue(m_Controls->Action.GetSeverity()); + m_Controls->RespirationRateSeverity->GetValue(m_Controls->Action.GetRespirationRateSeverity()); + m_Controls->TidalVolumeSeverity->GetValue(m_Controls->Action.GetTidalVolumeSeverity()); emit UpdateAction(m_Controls->Action, GetProcessTime()); } @@ -64,6 +70,8 @@ void QDyspneaWidget::ActionToControls(const SEDyspnea& action) { QActionWidget::ActionToControls(action); SEScalar data; - data.SetValue(action.GetSeverity()); - m_Controls->Severity->SetValue(data); + data.SetValue(action.GetRespirationRateSeverity()); + m_Controls->RespirationRateSeverity->SetValue(data); + data.SetValue(action.GetTidalVolumeSeverity()); + m_Controls->TidalVolumeSeverity->SetValue(data); } diff --git a/src/controls/actions/MechanicalVentilatorContinuousPositiveAirwayPressureWidget.cxx b/src/controls/actions/MechanicalVentilatorContinuousPositiveAirwayPressureWidget.cxx index 381de49c1a6d0a5d9b5f69b03e14d985bfd9a127..e3e339ea9dc97c069da025ce7334af321e93079a 100644 --- a/src/controls/actions/MechanicalVentilatorContinuousPositiveAirwayPressureWidget.cxx +++ b/src/controls/actions/MechanicalVentilatorContinuousPositiveAirwayPressureWidget.cxx @@ -57,7 +57,7 @@ QMechanicalVentilatorContinuousPositiveAirwayPressureWidget::QMechanicalVentilat m_Controls->DefaultAction.SetConnection(eSwitch::On); m_Controls->DefaultAction.GetFractionInspiredOxygen().SetValue(0.21); - m_Controls->DefaultAction.GetPositiveEndExpiredPressure().SetValue(5.0, PressureUnit::cmH2O); + m_Controls->DefaultAction.GetPositiveEndExpiratoryPressure().SetValue(5.0, PressureUnit::cmH2O); m_Controls->DefaultAction.GetDeltaPressureSupport().SetValue(8, PressureUnit::cmH2O); m_Controls->DefaultAction.GetSlope().SetValue(0.2, TimeUnit::s); @@ -105,7 +105,7 @@ void QMechanicalVentilatorContinuousPositiveAirwayPressureWidget::ControlsToActi m_Controls->Action.SetConnection((m_Controls->State->GetIndex() == 0) ? eSwitch::On : eSwitch::Off); m_Controls->FractionInspiredOxygen->GetValue(m_Controls->Action.GetFractionInspiredOxygen()); m_Controls->DeltaPressureSupport->GetValue(m_Controls->Action.GetDeltaPressureSupport()); - m_Controls->PositiveEndExpiredPressure->GetValue(m_Controls->Action.GetPositiveEndExpiredPressure()); + m_Controls->PositiveEndExpiredPressure->GetValue(m_Controls->Action.GetPositiveEndExpiratoryPressure()); m_Controls->Slope->GetValue(m_Controls->Action.GetSlope()); emit UpdateAction(m_Controls->Action, GetProcessTime()); @@ -114,10 +114,10 @@ void QMechanicalVentilatorContinuousPositiveAirwayPressureWidget::ActionToContro const SEMechanicalVentilatorContinuousPositiveAirwayPressure& action) { QActionWidget::ActionToControls(action); - m_Controls->Action.Copy(action); + m_Controls->Action.Copy(action, m_Controls->Pulse.GetScenario().GetSubstanceManager()); m_Controls->State->SetCurrentIndex((action.GetConnection() == eSwitch::On) ? 0 : 1); m_Controls->FractionInspiredOxygen->SetValue(m_Controls->Action.GetFractionInspiredOxygen()); m_Controls->DeltaPressureSupport->SetValue(m_Controls->Action.GetDeltaPressureSupport()); - m_Controls->PositiveEndExpiredPressure->SetValue(m_Controls->Action.GetPositiveEndExpiredPressure()); + m_Controls->PositiveEndExpiredPressure->SetValue(m_Controls->Action.GetPositiveEndExpiratoryPressure()); m_Controls->Slope->SetValue(m_Controls->Action.GetSlope()); } diff --git a/src/controls/actions/MechanicalVentilatorPressureControlWidget.cxx b/src/controls/actions/MechanicalVentilatorPressureControlWidget.cxx index 99eaad4b85bd4efb503fdf709b9041c276921536..621215cbd6750e49ad985839dff093947c2705c2 100644 --- a/src/controls/actions/MechanicalVentilatorPressureControlWidget.cxx +++ b/src/controls/actions/MechanicalVentilatorPressureControlWidget.cxx @@ -74,7 +74,7 @@ QMechanicalVentilatorPressureControlWidget::QMechanicalVentilatorPressureControl m_Controls->DefaultAction.GetInspiratoryPressure().SetValue(13.0, PressureUnit::cmH2O); m_Controls->DefaultAction.GetInspiratoryPeriod().SetValue(1.0, TimeUnit::s); m_Controls->DefaultAction.GetRespirationRate().SetValue(12, FrequencyUnit::Per_min); - m_Controls->DefaultAction.GetPositiveEndExpiredPressure().SetValue(5.0, PressureUnit::cmH2O); + m_Controls->DefaultAction.GetPositiveEndExpiratoryPressure().SetValue(5.0, PressureUnit::cmH2O); m_Controls->DefaultAction.GetSlope().SetValue(0.2, TimeUnit::s); Reset(); @@ -127,7 +127,7 @@ void QMechanicalVentilatorPressureControlWidget::ControlsToAction() m_Controls->InspiratoryPressure->GetValue(m_Controls->Action.GetInspiratoryPressure()); m_Controls->InspiratoryPeriod->GetValue(m_Controls->Action.GetInspiratoryPeriod()); m_Controls->RespirationRate->GetValue(m_Controls->Action.GetRespirationRate()); - m_Controls->PositiveEndExpiredPressure->GetValue(m_Controls->Action.GetPositiveEndExpiredPressure()); + m_Controls->PositiveEndExpiredPressure->GetValue(m_Controls->Action.GetPositiveEndExpiratoryPressure()); m_Controls->Slope->GetValue(m_Controls->Action.GetSlope()); emit UpdateAction(m_Controls->Action, GetProcessTime()); @@ -135,13 +135,13 @@ void QMechanicalVentilatorPressureControlWidget::ControlsToAction() void QMechanicalVentilatorPressureControlWidget::ActionToControls(const SEMechanicalVentilatorPressureControl& action) { QActionWidget::ActionToControls(action); - m_Controls->Action.Copy(action); + m_Controls->Action.Copy(action, m_Controls->Pulse.GetScenario().GetSubstanceManager()); m_Controls->State->SetCurrentIndex((action.GetConnection() == eSwitch::On) ? 0 : 1); m_Controls->Mode->SetCurrentIndex((action.GetMode() == eMechanicalVentilator_PressureControlMode::AssistedControl) ? 0 : 1); m_Controls->FractionInspiredOxygen->SetValue(m_Controls->Action.GetFractionInspiredOxygen()); m_Controls->InspiratoryPressure->SetValue(m_Controls->Action.GetInspiratoryPressure()); m_Controls->InspiratoryPeriod->SetValue(m_Controls->Action.GetInspiratoryPeriod()); m_Controls->RespirationRate->SetValue(m_Controls->Action.GetRespirationRate()); - m_Controls->PositiveEndExpiredPressure->SetValue(m_Controls->Action.GetPositiveEndExpiredPressure()); + m_Controls->PositiveEndExpiredPressure->SetValue(m_Controls->Action.GetPositiveEndExpiratoryPressure()); m_Controls->Slope->SetValue(m_Controls->Action.GetSlope()); } diff --git a/src/controls/actions/MechanicalVentilatorVolumeControlWidget.cxx b/src/controls/actions/MechanicalVentilatorVolumeControlWidget.cxx index 13ca01e3feb1927aadf0a38b40e0dbd0385101e0..f1b16b79fad71002d0376085cd64ea3e3d8f4173 100644 --- a/src/controls/actions/MechanicalVentilatorVolumeControlWidget.cxx +++ b/src/controls/actions/MechanicalVentilatorVolumeControlWidget.cxx @@ -66,7 +66,7 @@ QMechanicalVentilatorVolumeControlWidget::QMechanicalVentilatorVolumeControlWidg m_Controls->DefaultAction.GetTidalVolume().SetValue(600, VolumeUnit::mL); m_Controls->DefaultAction.GetInspiratoryPeriod().SetValue(1.0, TimeUnit::s); m_Controls->DefaultAction.GetRespirationRate().SetValue(12, FrequencyUnit::Per_min); - m_Controls->DefaultAction.GetPositiveEndExpiredPressure().SetValue(5.0, PressureUnit::cmH2O); + m_Controls->DefaultAction.GetPositiveEndExpiratoryPressure().SetValue(5.0, PressureUnit::cmH2O); m_Controls->DefaultAction.GetFlow().SetValue(50, VolumePerTimeUnit::L_Per_min); Properties()->layout()->addWidget(GetProcessTimeCtrl()); @@ -117,7 +117,7 @@ void QMechanicalVentilatorVolumeControlWidget::ControlsToAction() m_Controls->TidalVolume->GetValue(m_Controls->Action.GetTidalVolume()); m_Controls->InspiratoryPeriod->GetValue(m_Controls->Action.GetInspiratoryPeriod()); m_Controls->RespirationRate->GetValue(m_Controls->Action.GetRespirationRate()); - m_Controls->PositiveEndExpiredPressure->GetValue(m_Controls->Action.GetPositiveEndExpiredPressure()); + m_Controls->PositiveEndExpiredPressure->GetValue(m_Controls->Action.GetPositiveEndExpiratoryPressure()); m_Controls->Flow->GetValue(m_Controls->Action.GetFlow()); emit UpdateAction(m_Controls->Action, GetProcessTime()); @@ -125,12 +125,12 @@ void QMechanicalVentilatorVolumeControlWidget::ControlsToAction() void QMechanicalVentilatorVolumeControlWidget::ActionToControls(const SEMechanicalVentilatorVolumeControl& action) { QActionWidget::ActionToControls(action); - m_Controls->Action.Copy(action); + m_Controls->Action.Copy(action, m_Controls->Pulse.GetScenario().GetSubstanceManager()); m_Controls->State->SetCurrentIndex((action.GetConnection() == eSwitch::On) ? 0 : 1); m_Controls->FractionInspiredOxygen->SetValue(m_Controls->Action.GetFractionInspiredOxygen()); m_Controls->TidalVolume->SetValue(m_Controls->Action.GetTidalVolume()); m_Controls->InspiratoryPeriod->SetValue(m_Controls->Action.GetInspiratoryPeriod()); m_Controls->RespirationRate->SetValue(m_Controls->Action.GetRespirationRate()); - m_Controls->PositiveEndExpiredPressure->SetValue(m_Controls->Action.GetPositiveEndExpiredPressure()); + m_Controls->PositiveEndExpiredPressure->SetValue(m_Controls->Action.GetPositiveEndExpiratoryPressure()); m_Controls->Flow->SetValue(m_Controls->Action.GetFlow()); } diff --git a/src/controls/actions/PneumoniaExacerbationWidget.cxx b/src/controls/actions/PneumoniaExacerbationWidget.cxx index 62d6ac08baf91e8a1acced24ed934ff862052cca..177d33018ed25242d1224a0edf644f5aa8ea29bc 100644 --- a/src/controls/actions/PneumoniaExacerbationWidget.cxx +++ b/src/controls/actions/PneumoniaExacerbationWidget.cxx @@ -22,7 +22,7 @@ QPneumoniaExacerbationWidget::QPneumoniaExacerbationWidget(QPulse& qp, QWidget * { m_Controls = new Controls(qp); m_Controls->LeftLungSeverity = new QScalarWidget("Left Lung Severity", 0, 1, 0.1, ScalarOptionWidget::None, this); - m_Controls->RightLungSeverity = new QScalarWidget("Right LungA ffected", 0, 1, 0.1, ScalarOptionWidget::None, this); + m_Controls->RightLungSeverity = new QScalarWidget("Right Lung Severity", 0, 1, 0.1, ScalarOptionWidget::None, this); Properties()->layout()->addWidget(m_Controls->LeftLungSeverity); Properties()->layout()->addWidget(m_Controls->RightLungSeverity); Properties()->layout()->addWidget(GetProcessTimeCtrl()); diff --git a/src/ui/Enviornment.ui b/src/ui/Environment.ui similarity index 96% rename from src/ui/Enviornment.ui rename to src/ui/Environment.ui index 0decaf5da17bd08983f113bc62d513957351a3bd..b2f6f814169ac16181aa407f8804dab4933c5398 100644 --- a/src/ui/Enviornment.ui +++ b/src/ui/Environment.ui @@ -1,7 +1,7 @@ - EnviornmentWidget - + EnvironmentWidget + 0 @@ -18,8 +18,8 @@ - 757 - 337 + 787 + 352 @@ -37,7 +37,7 @@ DockWidget - + 0 @@ -102,7 +102,7 @@ 0 0 331 - 421 + 415 @@ -141,8 +141,8 @@ 0 0 - 304 - 197 + 294 + 193 @@ -175,8 +175,8 @@ 0 0 - 304 - 197 + 294 + 192 @@ -304,7 +304,7 @@ - + Save Environment File diff --git a/src/ui/MainExplorerWindow.ui b/src/ui/MainExplorerWindow.ui index 99f0316ebf9bda20e09c66bb21e0f516573887af..29d0e352f94568eb023bb07afd51475ef432d8eb 100644 --- a/src/ui/MainExplorerWindow.ui +++ b/src/ui/MainExplorerWindow.ui @@ -14,7 +14,7 @@ Pulse Explorer - + @@ -138,13 +138,28 @@ + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - 5 + 6 @@ -157,6 +172,21 @@ ParaView + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + @@ -173,6 +203,21 @@ Vitals Monitor + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + @@ -185,19 +230,304 @@ 0 + + + + + + + 211 + 211 + 211 + + + + + + + 170 + 255 + 0 + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + + + + 211 + 211 + 211 + + + + + + + 170 + 255 + 0 + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + + + + 211 + 211 + 211 + + + + + + + 170 + 255 + 0 + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + - #DataRequestsTab { background: lightgrey } + QWidget#DataRequestsTab { background: lightgrey } Data Requests + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - + + + + 0 + 0 + + + + + + + + + 211 + 211 + 211 + + + + + + + 240 + 240 + 240 + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + + + + 211 + 211 + 211 + + + + + + + 240 + 240 + 240 + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + + + + 211 + 211 + 211 + + + + + + + 240 + 240 + 240 + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + + + QWidget#ModifierTab { background: lightgrey } + + + Modifiers + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + 0 @@ -205,7 +535,7 @@ - true + false QWidget#EnvironmentTab { background: lightgrey } @@ -214,8 +544,23 @@ Environment + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + - + @@ -236,6 +581,21 @@ Scenario + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + @@ -255,6 +615,21 @@ Ventilator + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + @@ -292,6 +667,18 @@ + + 0 + + + 0 + + + 0 + + + 0 + @@ -311,10 +698,13 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt;"><br /></p></body></html> +hr { height: 1px; border-width: 0; } +li.unchecked::marker { content: "\2610"; } +li.checked::marker { content: "\2612"; } +</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:12pt;"><br /></p></body></html> @@ -330,7 +720,7 @@ p, li { white-space: pre-wrap; } 0 0 1440 - 21 + 22 diff --git a/src/ui/Modifiers.ui b/src/ui/Modifiers.ui new file mode 100644 index 0000000000000000000000000000000000000000..ca30660864cd0aebede784d9c1f516f494dad9f7 --- /dev/null +++ b/src/ui/Modifiers.ui @@ -0,0 +1,229 @@ + + + ModifiersWidget + + + + 0 + 0 + 915 + 747 + + + + + 0 + 0 + + + + + 787 + 747 + + + + + 524287 + 524287 + + + + true + + + QDockWidget::NoDockWidgetFeatures + + + DockWidget + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + + 0 + 0 + + + + + + + + 0 + 0 + + + + + + + Cardiovascular Modifiers + + + + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOn + + + true + + + + + 0 + 0 + 380 + 599 + + + + + + + + + + + + Reset + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Apply + + + + + + + + + + + + + + + + + + Respiratory Modifiers + + + + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOn + + + true + + + + + 0 + 0 + 379 + 599 + + + + + + + + + + + + Reset + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Apply + + + + + + + + + + + + + + + + + + + + diff --git a/src/ui/Ventilator.ui b/src/ui/Ventilator.ui index 2fb54dbf7250fc03519cf8b5b3e55c782196807a..239f7a553f9e1ac39d41440eb0f3aba6b815f781 100644 --- a/src/ui/Ventilator.ui +++ b/src/ui/Ventilator.ui @@ -26,6 +26,9 @@ 0 + + 6 + @@ -50,6 +53,21 @@ QFrame::Raised + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + @@ -75,116 +93,285 @@ - 40 + 60 20 - + + + + 0 + 0 + + - 150 + 300 0 - - QFrame::StyledPanel + + + 300 + 16777215 + - - QFrame::Raised + + 0 - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - false - - - Hold - - - - - - - false - - - Disconnect - - - - - - - Connect - - - - - - - - NONE - - - - - PC-CMV - - - - - PC-AC - - - - - VC-CMV - - - - - VC-AC - - - + + false + + + + QWidget#ModeTab { background: #F0F0F0 } + + + Mode + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + Qt::Horizontal + + + + 15 + 20 + + + + + + + + + 132 + 0 + + + + + NONE + + + + + PC-CMV + + + + + PC-AC + + + + + VC-CMV + + + + + VC-AC + + + + + CPAP + + + + + + + + + + + + Connect + + + + + + + false + + + Disconnect + + + + + + + + + + + false + + + Hold + + + + + + + Reset + + + + + + + - CPAP + Show Loops - - - - - - - Loops - - - - - - - Reset - - - - + + + + + + + QWidget#TriggerTab { background: #F0F0F0 } + + + Triggers + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 80 + 0 + + + + Apply + + + + + + + + + + QWidget#DrugTab { background: #F0F0F0 } + + + Drugs + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 80 + 0 + + + + Apply + + + + + + + @@ -266,6 +453,18 @@ QFrame::Sunken + + 0 + + + 0 + + + 0 + + + 0 + @@ -327,7 +526,6 @@ - 75 true @@ -356,7 +554,6 @@ - 75 true @@ -390,7 +587,6 @@ - 75 true @@ -416,7 +612,6 @@ - 75 true @@ -433,7 +628,6 @@ 12 - 75 true @@ -457,7 +651,6 @@ 12 - 75 true @@ -488,7 +681,6 @@ - 75 true @@ -517,7 +709,6 @@ - 75 true @@ -537,7 +728,6 @@ 12 - 75 true diff --git a/src/ui/dark_tab.xml b/src/ui/dark_tab.xml new file mode 100644 index 0000000000000000000000000000000000000000..3ac35513d96c1b65d5ef8ef405e5b353c81ccefc --- /dev/null +++ b/src/ui/dark_tab.xml @@ -0,0 +1,90 @@ + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + + + 211 + 211 + 211 + + + + + diff --git a/src/ui/default_tab.xml b/src/ui/default_tab.xml new file mode 100644 index 0000000000000000000000000000000000000000..b8fafb2b667af4fd7f647bd0e9d84a005270aab0 --- /dev/null +++ b/src/ui/default_tab.xml @@ -0,0 +1,6 @@ + + + + + +