Commit 39db3124 authored by Tiago Sarmento's avatar Tiago Sarmento

merged

parents 54486e5a 32d22a41
Pipeline #1585 canceled with stages
......@@ -19,7 +19,7 @@ env/
ansible/playbooks/hosts
.idea
scratch_*
NativeUI/configs/startup_config.json
*/*/startup_config.json
# python virtual env created using ansible
.hev_env
......
......@@ -7,6 +7,9 @@ Command-line arguments:
-d, --debug : set the level of debug output.Include once for INFO, twice for DEBUG
-w, --windowed : run the user interface in windowed mode.
-r, --resolution : set the window size in pixels. E.g. -r 1920x1080
--no-startup : start the UI without going through the calibration startup sequence.
-l, --language : set the initial language for the UI (can later be set within the
interface). Defaults to English.
"""
__author__ = ["Benjamin Mummery", "Dónal Murray", "Tiago Sarmento"]
......@@ -74,32 +77,43 @@ class NativeUI(HEVClient, QMainWindow):
Subclassed HEVClient for client logic, and QMainWindow for display.
Extends its base classes with the following methods:
__define_connections - connects widget signals and slots to allow the UI to
- __define_connections - connects widget signals and slots to allow the UI to
function. Called once during initialisation.
__find icons - locate the directory containing icons used for UI buttons and
- __find icons - locate the directory containing icons used for UI buttons and
displays. Called once during initialisation.
__find_configs - locate the directory containing config files used by the UI. Called
- __find_configs - locate the directory containing config files used by the UI. Called
once during initialisation.
set_current_mode - TODO: deprecated, remove.
- set_current_mode - TODO: deprecated, remove.
get_updates - Overrides the placeholder get_updates method of HEVClient. Passes
- get_updates - Overrides the placeholder get_updates method of HEVClient. Passes
payloads to handlers. Called whenever a new payload is read in.
change_page (Slot) - switches the page shown in the page_stack. Called whent the
- change_page (Slot) - switches the page shown in the page_stack. Called whent the
page buttons are pressed or whenever a popup needs to show a specific page.
q_send_cmd (Slot) - send a command to the MCU.
- q_send_cmd (Slot) - send a command to the MCU.
- q_ack_alarm (Slot) - acknowledge a recieved alarm.
q_ack_alarm (Slot) - acknowledge a recieved alarm.
- q_send_personal (Slot) - send personal information to the MCU.
q_send_personal (Slot) - send personal information to the MCU.
Also adds the following keyword arguments:
- resolution
- skip_startup
- language
"""
def __init__(self, resolution: list, *args, skip_startup=False, **kwargs):
def __init__(
self,
*args,
resolution: list = [1920, 1080],
skip_startup: bool = False,
language: str = "english",
**kwargs,
):
super().__init__(*args, **kwargs)
# store variable to change editability of screen - implemented in screen locking
......@@ -121,8 +135,22 @@ class NativeUI(HEVClient, QMainWindow):
self.colors = json.load(infile)
for key in self.colors:
self.colors[key] = QColor.fromRgb(*self.colors[key])
with open(os.path.join(config_path, "text_english.json")) as infile:
# Import the specified language config file
language_config = os.path.join(config_path, "text_%s.json" % language)
if not language_config in self.localisation_files:
logging.error(
"No config file for %s language (expected file at %s), defaulting to %s",
(language, language_config, self.localisation_files[0]),
)
language_config = self.localisation_files[0]
with open(language_config) as infile:
self.text = json.load(infile)
# Reorder localisation_files so that the language used is the first index
self.localisation_files.insert(
0,
self.localisation_files.pop(self.localisation_files.index(language_config)),
)
# Set up fonts based on the screen resolution. text_font and value_font are 20
# and 40px respectively for 1920*1080.
......@@ -170,8 +198,12 @@ class NativeUI(HEVClient, QMainWindow):
self.alarm_handler,
]
self.messageCommandPopup = SetConfirmPopup(self)
self.typeValPopupNum = AbstractTypeValPopup(self,'numeric')#TypeValuePopup(self, NumberpadWidget(self))
self.typeValPopupAlpha = AbstractTypeValPopup(self,'alpha')#TypeValuePopup(self, AlphapadWidget(self))
self.typeValPopupNum = AbstractTypeValPopup(
self, "numeric"
) # TypeValuePopup(self, NumberpadWidget(self))
self.typeValPopupAlpha = AbstractTypeValPopup(
self, "alpha"
) # TypeValuePopup(self, AlphapadWidget(self))
# Create all of the widgets and place them in the layout.
self.widgets = Widgets(self)
......@@ -194,7 +226,7 @@ class NativeUI(HEVClient, QMainWindow):
self.typeValPopupNum,
self.typeValPopupAlpha,
self.messageCommandPopup,
#self.confirmPopup,
# self.confirmPopup,
self.main_display,
self.startupWidget,
]:
......@@ -301,7 +333,8 @@ class NativeUI(HEVClient, QMainWindow):
)
)
# TODO: command sending
# Startup next and skip buttons should move from the startup widget to the main
# display
self.widgets.nextButton.pressed.connect(
lambda: self.display_stack.setCurrentWidget(self.main_display)
)
......@@ -310,6 +343,11 @@ class NativeUI(HEVClient, QMainWindow):
)
self.widgets.lock_button.PageButtonPressed.connect(self.toggle_editability)
# Startup next button should send the ventilator start command.
self.widgets.nextButton.pressed.connect(
lambda: self.q_send_cmd("GENERAL", "START")
)
# Battery Display should update when we get battery info
self.battery_handler.UpdateBatteryDisplay.connect(
self.widgets.battery_display.update_status
......@@ -534,7 +572,15 @@ class NativeUI(HEVClient, QMainWindow):
self.widgets.detailed_plots,
self.widgets.circle_plots,
self.widgets.ventilator_start_stop_buttons_widget,
# self.widgets.charts_widget,
self.widgets.charts_widget,
self.widgets.plot_stack,
self.widgets.alarms_page,
self.widgets.settings_page,
self.widgets.modes_page,
self.widgets.modes_stack,
self.widgets.startup_stack,
self.widgets.mode_settings_stack,
self.widgets.mode_settings_stack_startup,
# self.widgets.spin_buttons,
# self.widgets.mode_personal_tab,
]:
......@@ -704,6 +750,20 @@ def parse_command_line_arguments() -> argparse.Namespace:
default=False,
help="Run the UI without the startup sequence",
)
parser.add_argument(
"-l",
"--language",
action="store",
dest="language",
default="English",
type=str,
help="""
Set the language for the UI from the following list:\n
Language Recognised Values\n
English e, E, english, English\n
Portugues p, P, portugues, Portugues
""",
)
return parser.parse_args()
......@@ -723,6 +783,27 @@ def set_logging_level(debug_level: int) -> int:
return 0
def interpret_language(input_string: str) -> str:
"""
Convert the value given for the language CLA to one that NativeUI can interpret.
"""
default_language = "English"
if input_string is None:
return default_language
keys_english = ["e", "E", "english", "English"]
keys_portugues = ["p", "P", "portugues", "Portugues", "portuguese", "Portuguese"]
if input_string in keys_english:
return "english"
if input_string in keys_portugues:
return "portuguese"
logging.error(
"Unrecognised language value %s, defaulting to %s",
(input_string, default_language),
)
return default_language
def interpret_resolution(input_string: str) -> list:
"""
Convert a string to a pair of numbers specifying the window size.
......@@ -781,8 +862,9 @@ if __name__ == "__main__":
# setup pyqtplot widget
app = QApplication(sys.argv)
dep = NativeUI(
interpret_resolution(command_line_args.resolution),
resolution=interpret_resolution(command_line_args.resolution),
skip_startup=command_line_args.no_startup,
language=interpret_language(command_line_args.language),
)
set_window_size(
dep,
......
{"calibration": {"label": "calibration", "last_performed": 1620695901, "cmd_code": "calib_rate"}, "leak_test": {"label": "Leak Test", "last_performed": 1620695902, "cmd_code": "leak_test"}, "maintenance": {"label": "maintenance", "last_performed": 1620695905, "cmd_code": "main_tenance"}}
\ No newline at end of file
{"calibration": {"label": "calibration", "last_performed": 1621526657, "cmd_code": "calib_rate"}, "leak_test": {"label": "Leak Test", "last_performed": 1621526657, "cmd_code": "leak_test"}, "maintenance": {"label": "maintenance", "last_performed": 1621526658, "cmd_code": "main_tenance"}}
......@@ -3,6 +3,10 @@
"start_button": "START",
"stop_button": "STOP",
"standby_button": "STANDBY",
"PC/AC": "PC/AC",
"PC/AC-PRVC": "PC/AC-PRVC",
"PC-PSV": "PC-PSV",
"CPAP": "CPAP",
"plot_axis_label_pressure": "Pressure [cmH<sub>2</sub>O]",
"plot_axis_label_flow": "Flow [L/min]",
"plot_axis_label_volume": "Volume [mL]",
......@@ -16,6 +20,15 @@
"layout_label_measurements": "Measurements",
"button_label_main_normal": "Normal",
"button_label_main_detailed": "Detailed",
"button_label_alarms_list": "List of Alarms",
"button_label_alarms_table": "Alarm Table",
"button_label_alarms_clinical": "Clinical Limits",
"button_label_settings_expert": "Expert",
"button_label_settings_charts": "Charts",
"button_label_settings_info": "System Info",
"button_label_modes_mode": "Mode Settings",
"button_label_modes_personal": "Personal Settings",
"button_label_modes_summary": "Summary",
"ui_window_title": "HEV NativeUI v{version}",
"measurement_label_plateau_pressure": "P<sub>PLATEAU</sub> [cmH<sub>2</sub>O]",
"measurement_label_respiratory_rate": "RR",
......
......@@ -3,6 +3,10 @@
"start_button": "INICIAR",
"stop_button": "PARAR",
"standby_button": "ESPERAR",
"PC/AC": "PC/AC",
"PC/AC-PRVC": "PC/AC-PRVC",
"PC-PSV": "PC-PSV",
"CPAP": "CPAP",
"plot_axis_label_pressure": "Pressao [cmH<sub>2</sub>O]",
"plot_axis_label_flow": "Fluxo [L/min]",
"plot_axis_label_volume": "Volume [mL]",
......@@ -16,6 +20,15 @@
"layout_label_measurements": "Medicoes",
"button_label_main_normal": "Normal",
"button_label_main_detailed": "Detalhado",
"button_label_alarms_list": "-",
"button_label_alarms_table": "-",
"button_label_alarms_clinical": "-",
"button_label_settings_expert": "-",
"button_label_settings_charts": "-",
"button_label_settings_info": "-",
"button_label_modes_mode": "-",
"button_label_modes_personal": "-",
"button_label_modes_summary": "-",
"ui_window_title": "HEV NativeUI v{version}",
"measurement_label_plateau_pressure": "P<sub>Plato</sub> [cmH<sub>2</sub>O]",
"measurement_label_respiratory_rate": "FREQ<sub>RESP</sub>",
......
......@@ -83,13 +83,18 @@ class Layout:
# Stack the data collection pages.
self.widgets.add_widget(
SwitchableStackWidget(
self.NativeUI,
self.NativeUI.colors,
self.NativeUI.text,
[
self.layout_mode_startup(),
self.layout_mode_personal("startup_", False),
self.layout_startup_confirmation(),
],
["Mode Settings", "Personal Settings", "Summary"],
[
"button_label_modes_mode",
"button_label_modes_personal",
"button_label_modes_summary",
],
),
"startup_stack",
)
......@@ -246,12 +251,10 @@ class Layout:
# Put the normal and detailed views into a switchable stack
self.widgets.add_widget(
SwitchableStackWidget(
self.NativeUI,
self.NativeUI.colors,
self.NativeUI.text,
[tab_main_normal, tab_main_detailed],
[
self.NativeUI.text["button_label_main_normal"],
self.NativeUI.text["button_label_main_detailed"],
],
["button_label_main_normal", "button_label_main_detailed"],
),
"plot_stack",
)
......@@ -290,13 +293,18 @@ class Layout:
alarm_table_tab_widgets = [self.widgets.alarm_table]
page_alarms = SwitchableStackWidget(
self.NativeUI,
self.NativeUI.colors,
self.NativeUI.text,
[
self.layout_tab_alarm_list(alarm_tab_widgets),
self.layout_tab_alarm_table(alarm_table_tab_widgets),
self.layout_tab_clinical_limits(),
],
["List of Alarms", "Alarm Table", "Clinical Limits"],
[
"button_label_alarms_list",
"button_label_alarms_table",
"button_label_alarms_clinical",
],
)
page_alarms.setFont(self.NativeUI.text_font)
return page_alarms
......@@ -326,9 +334,14 @@ class Layout:
# Create the stack
page_settings = SwitchableStackWidget(
self.NativeUI,
[tab_charts, tab_info, self.layout_settings_expert()],
["Charts", "Info", "Expert"],
self.NativeUI.colors,
self.NativeUI.text,
[tab_charts, tab_info,self.layout_settings_expert(),],
[
"button_label_settings_charts",
"button_label_settings_info",
"button_label_settings_expert",
],
)
page_settings.setFont(self.NativeUI.text_font)
self.widgets.add_widget(page_settings, "setting_stack")
......@@ -348,12 +361,13 @@ class Layout:
# )
modes_stack = SwitchableStackWidget(
self.NativeUI,
self.NativeUI.colors,
self.NativeUI.text,
[
self.layout_mode_settings(True),
self.layout_mode_personal("", True),
], # self.widgets.mode_personal_tab],
["Mode Settings", "Personal Settings"],
["button_label_modes_mode", "button_label_modes_personal"],
)
modes_stack.setFont(self.NativeUI.text_font)
self.widgets.add_widget(modes_stack, "modes_stack")
......@@ -478,8 +492,10 @@ class Layout:
)
page_modes = SwitchableStackWidget(
self.NativeUI, mode_pages, self.NativeUI.modeList
self.NativeUI.colors, self.NativeUI.text, mode_pages, self.NativeUI.modeList
)
self.widgets.add_widget(page_modes, "mode_settings_stack")
page_modes.setFont(self.NativeUI.text_font)
return page_modes
......@@ -556,9 +572,10 @@ class Layout:
)
mode_stack = SwitchableStackWidget(
self.NativeUI, mode_pages, self.NativeUI.modeList
self.NativeUI.colors, self.NativeUI.text, mode_pages, self.NativeUI.modeList
)
mode_stack.setFont(self.NativeUI.text_font)
self.widgets.add_widget(mode_stack, "mode_settings_stack_startup")
hRadioLayout = QtWidgets.QHBoxLayout()
for mode in self.NativeUI.modeList:
......
......@@ -308,13 +308,7 @@ class ChartsPlotWidget(QtWidgets.QWidget):
# Add the plot axes to the graph widget
self.display_plot = self.graph_widget.addPlot()
self.display_plot.setLabel("left", "????", **labelStyle)
self.display_plot.setLabel(
"bottom",
"????",
**labelStyle
# labels={"left": "????", "bottom": "????"}
)
self.display_plot.setLabel("bottom", "????", **labelStyle)
self.display_plot.getAxis("left").setTextPen("w")
self.display_plot.getAxis("bottom").setTextPen("w")
......@@ -392,11 +386,13 @@ class ChartsPlotWidget(QtWidgets.QWidget):
def localise_text(self, text: dict) -> int:
"""
Update the text displayed on the axis' and legend of time plots.
Currently a placeholder.
"""
self.pressure_plot.setLabel("left", text["plot_axis_label_pressure"])
self.pressure_plot.legend.clear()
self.pressure_plot.legend.addItem(
self.pressure_line, text["plot_line_label_pressure"]
)
self.display_plot.setLabel("left", text["plot_axis_label_pressure"])
# self.display_plot.legend.clear()
# self.display_plot.legend.addItem(
# self.pressure_line, text["plot_line_label_pressure"]
# )
return 0
......@@ -7,23 +7,22 @@ from PySide2.QtGui import QFont
class SwitchableStackWidget(QtWidgets.QWidget):
def __init__(
self, NativeUI, widget_list: list, button_labels: list, *args, **kwargs
self, colors, text, widget_list: list, button_label_keys: list, *args, **kwargs
):
super().__init__(*args, **kwargs)
self.NativeUI = NativeUI
self.widget_list = widget_list
self.button_list = self.__make_buttons(button_labels)
self.button_list = self.__make_buttons(colors, text, button_label_keys)
self.__build()
if len(self.button_list) > 0:
self.setTab(self.button_list[0])
def rebuild(self, widget_list, button_labels):
def rebuild(self, colors, text, widget_list, button_label_keys):
"""
For an already created SwitchableStackWidget, change the tabs in the stack.
"""
self.__clear()
self.widget_list = widget_list
self.button_list = self.__make_buttons(button_labels)
self.button_list = self.__make_buttons(colors, text, button_label_keys)
self.__build()
self.setTab(self.button_list[0])
return 0
......@@ -55,11 +54,14 @@ class SwitchableStackWidget(QtWidgets.QWidget):
vlayout.addWidget(self.stack)
self.setLayout(vlayout)
def __make_buttons(self, button_labels: list) -> list:
def __make_buttons(self, colors, text, button_label_keys: list) -> list:
"""
Make the selector buttons
"""
return [SelectorButtonWidget(self.NativeUI, label) for label in button_labels]
return [
SelectorButtonWidget(colors, text, label_key)
for label_key in button_label_keys
]
def setTab(self, button_pressed) -> int:
"""
......@@ -104,27 +106,34 @@ class SwitchableStackWidget(QtWidgets.QWidget):
raise AttributeError("setButtonSize called without usable size information")
return 0
def localise_text(self, text: dict) -> int:
for button in self.button_list:
button.localise_text(text)
return 0
class SelectorButtonWidget(QtWidgets.QPushButton):
def __init__(self, NativeUI, *args, **kwargs):
super().__init__(*args, **kwargs)
def __init__(self, colors: dict, text: dict, label_key: str, *args, **kwargs):
super().__init__(text[label_key], *args, **kwargs)
self.__label_key = label_key
style = (
"QPushButton[selected='0']{"
" color: " + NativeUI.colors["button_foreground_enabled"].name() + ";"
" background-color: "
+ NativeUI.colors["button_background_enabled"].name()
+ ";"
" color: " + colors["button_foreground_enabled"].name() + ";"
" background-color: " + colors["button_background_enabled"].name() + ";"
" border:none"
"}"
"QPushButton[selected='1']{"
" color: " + NativeUI.colors["button_foreground_disabled"].name() + ";"
" background-color:"
+ NativeUI.colors["button_background_disabled"].name()
+ ";"
" color: " + colors["button_foreground_disabled"].name() + ";"
" background-color:" + colors["button_background_disabled"].name() + ";"
" border:none"
"}"
)
self.setStyleSheet(style)
self.setProperty("selected", "0")
def localise_text(self, text: dict) -> int:
self.setText(text[self.__label_key])
return 0
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment