Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
H
HEV - High Energy Ventilator
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
5
Issues
5
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
HEV - High Energy Ventilator
Commits
05db8768
Commit
05db8768
authored
May 26, 2021
by
Karol Hennessy
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'ui_dev' into test_UI_new_state_machines_merge
parents
d7013674
fabb9426
Pipeline
#1589
failed with stages
Changes
20
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
424 additions
and
306 deletions
+424
-306
NativeUI.py
NativeUI/NativeUI.py
+67
-11
alarm_popup.py
NativeUI/alarm_widgets/alarm_popup.py
+34
-28
alarm_table.py
NativeUI/alarm_widgets/alarm_table.py
+25
-38
clinical_config.json
NativeUI/configs/clinical_config.json
+1
-1
colors.json
NativeUI/configs/colors.json
+10
-10
mode_config.json
NativeUI/configs/mode_config.json
+2
-2
global_send_popup.py
NativeUI/global_widgets/global_send_popup.py
+18
-14
global_typeval_popup.py
NativeUI/global_widgets/global_typeval_popup.py
+12
-9
tab_modeswitch_button.py
NativeUI/global_widgets/tab_modeswitch_button.py
+34
-68
clinical_handler.py
NativeUI/mode_widgets/clinical_handler.py
+7
-0
mode_handler.py
NativeUI/mode_widgets/mode_handler.py
+17
-1
ui_layout.py
NativeUI/ui_layout.py
+8
-7
ui_widgets.py
NativeUI/ui_widgets.py
+10
-8
expert_handler.py
NativeUI/widget_library/expert_handler.py
+3
-0
page_buttons_widget.py
NativeUI/widget_library/page_buttons_widget.py
+23
-33
plot_widget.py
NativeUI/widget_library/plot_widget.py
+7
-7
spin_buttons_widget.py
NativeUI/widget_library/spin_buttons_widget.py
+0
-1
switchable_stack_widget.py
NativeUI/widget_library/switchable_stack_widget.py
+6
-1
CommsCommon.py
raspberry-dataserver/CommsCommon.py
+17
-0
hevserver.py
raspberry-dataserver/hevserver.py
+123
-67
No files found.
NativeUI/NativeUI.py
View file @
05db8768
...
...
@@ -7,12 +7,15 @@ 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"
]
__credits__
=
[
"Benjamin Mummery"
,
"Dónal Murray"
,
"Tim Powell"
,
"Tiago Sarmento"
]
__license__
=
"GPL"
__version__
=
"0.1.
1
"
__version__
=
"0.1.
2
"
__maintainer__
=
"Benjamin Mummery"
__email__
=
"benjamin.mummery@stfc.ac.uk"
__status__
=
"Prototype"
...
...
@@ -113,6 +116,9 @@ class NativeUI(HEVClient, QMainWindow):
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
# store variable to change editability of screen - implemented in screen locking
self
.
enableState
=
True
# Set the resolution of the display window
self
.
screen_width
=
resolution
[
0
]
self
.
screen_height
=
resolution
[
1
]
...
...
@@ -148,8 +154,12 @@ class NativeUI(HEVClient, QMainWindow):
# Set up fonts based on the screen resolution. text_font and value_font are 20
# and 40px respectively for 1920*1080.
self
.
text_font
=
QFont
(
"Sans Serif"
,
resolution
[
0
]
/
96
)
self
.
value_font
=
QFont
(
"Sans Serif"
,
2
*
resolution
[
0
]
/
96
)
self
.
text_font
=
QFont
(
"Sans Serif"
,
int
(
resolution
[
0
]
/
96
))
self
.
value_font
=
QFont
(
"Sans Serif"
,
int
(
2
*
resolution
[
0
]
/
96
))
# Set the popup size based on the screen resolution. alarm_popup_width is 400
# for 1920*1080
self
.
alarm_popup_width
=
int
(
resolution
[
0
]
/
4.8
)
# Import icons
self
.
icons
=
{
...
...
@@ -157,6 +167,7 @@ class NativeUI(HEVClient, QMainWindow):
"button_alarms_page"
:
"exclamation-triangle-solid"
,
"button_modes_page"
:
"fan-solid"
,
"button_settings_page"
:
"sliders-h-solid"
,
"lock_screen"
:
"lock-solid"
,
}
self
.
iconext
=
"png"
self
.
iconpath
=
self
.
__find_icons
(
self
.
iconext
)
...
...
@@ -169,6 +180,8 @@ class NativeUI(HEVClient, QMainWindow):
palette
=
self
.
palette
()
palette
.
setColor
(
QPalette
.
Window
,
self
.
colors
[
"page_background"
])
self
.
alt_palette
=
self
.
palette
()
# Set up the handlers
self
.
battery_handler
=
BatteryHandler
()
self
.
data_handler
=
DataHandler
(
plot_history_length
=
1000
)
...
...
@@ -324,7 +337,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
)
)
...
...
@@ -332,6 +346,12 @@ class NativeUI(HEVClient, QMainWindow):
lambda
:
self
.
display_stack
.
setCurrentWidget
(
self
.
main_display
)
)
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
...
...
@@ -372,6 +392,12 @@ class NativeUI(HEVClient, QMainWindow):
lambda
:
self
.
display_stack
.
setCurrentWidget
(
self
.
startupWidget
)
)
self
.
typeValPopupNum
.
okButton
.
pressed
.
connect
(
self
.
typeValPopupNum
.
handle_ok_press
)
self
.
typeValPopupAlpha
.
okButton
.
pressed
.
connect
(
self
.
typeValPopupNum
.
handle_ok_press
)
##### Mode:
# When mode is switched from mode page, various other locations must respond
for
widget
in
self
.
mode_handler
.
spinDict
.
values
():
...
...
@@ -433,18 +459,26 @@ class NativeUI(HEVClient, QMainWindow):
button_widget
.
pressed
.
connect
(
lambda
i
=
key
:
self
.
mode_handler
.
handle_okbutton_click
(
i
)
)
button_widget
.
pressed
.
connect
(
self
.
clinical_handler
.
commandSent
)
elif
isinstance
(
button_widget
,
CancelButtonWidget
):
mode
=
self
.
mode_handler
.
get_mode
(
key
)
button_widget
.
pressed
.
connect
(
self
.
mode_handler
.
commandSent
)
buttonMode
=
self
.
mode_handler
.
get_mode
(
key
)
button_widget
.
pressed
.
connect
(
lambda
i
=
buttonMode
:
self
.
mode_handler
.
handle_cancel_pressed
(
i
)
)
button_widget
.
pressed
.
connect
(
lambda
i
=
buttonMode
:
self
.
clinical_handler
.
handle_cancel_pressed
(
i
)
)
for
key
,
button_widget
in
self
.
mode_handler
.
mainButtonDict
.
items
():
if
isinstance
(
button_widget
,
(
OkButtonWidget
)):
button_widget
.
clicked
.
connect
(
self
.
mode_handler
.
handle_mainokbutton_click
)
button_widget
.
pressed
.
connect
(
self
.
clinical_handler
.
commandSent
)
elif
isinstance
(
button_widget
,
CancelButtonWidget
):
# mode = self.mode_handler.get_mode(key)
button_widget
.
clicked
.
connect
(
self
.
mode_handler
.
commandSent
)
button_widget
.
pressed
.
connect
(
self
.
clinical_handler
.
commandSent
)
for
key
,
spin_widget
in
self
.
clinical_handler
.
limSpinDict
.
items
():
spin_widget
.
simpleSpin
.
manualChanged
.
connect
(
...
...
@@ -472,8 +506,8 @@ class NativeUI(HEVClient, QMainWindow):
self
.
clinical_handler
.
handle_cancelbutton_click
)
# for widget in (self.clinical_handler.setSpinDict.values()
):
#
self.clinical_handler.UpdateClinical.connect(widget.update_value)
for
widget
in
self
.
clinical_handler
.
setSpinDict
.
values
(
):
self
.
clinical_handler
.
UpdateClinical
.
connect
(
widget
.
update_value
)
self
.
mode_handler
.
OpenPopup
.
connect
(
self
.
messageCommandPopup
.
populatePopup
)
self
.
mode_handler
.
OpenPopup
.
connect
(
...
...
@@ -500,6 +534,13 @@ class NativeUI(HEVClient, QMainWindow):
)
##### Expert Settings:
self
.
widgets
.
expert_password_widget
.
okButton
.
pressed
.
connect
(
self
.
widgets
.
expert_password_widget
.
submit_password
)
self
.
widgets
.
expert_password_widget
.
correctPassword
.
connect
(
lambda
:
self
.
widgets
.
expert_passlock_stack
.
setCurrentIndex
(
1
)
)
# Expert handler should respond to manual value changes
for
key
,
spin_widget
in
self
.
expert_handler
.
spinDict
.
items
():
spin_widget
.
simpleSpin
.
manualChanged
.
connect
(
...
...
@@ -640,12 +681,30 @@ class NativeUI(HEVClient, QMainWindow):
return
0
def
toggle_editability
(
self
):
"""Set all widgets disabled to lock screen"""
self
.
enableState
=
not
self
.
enableState
if
self
.
enableState
:
self
.
alt_palette
.
setColor
(
QPalette
.
Window
,
self
.
colors
[
"page_background"
])
else
:
self
.
alt_palette
.
setColor
(
QPalette
.
Window
,
self
.
colors
[
"page_foreground"
])
self
.
setPalette
(
self
.
alt_palette
)
for
attribute
in
dir
(
self
.
widgets
):
widg
=
self
.
widgets
.
get_widget
(
attribute
)
if
isinstance
(
widg
,
QWidget
):
widg
.
setEnabled
(
self
.
enableState
)
self
.
widgets
.
lock_button
.
setEnabled
(
True
)
@
Slot
(
str
)
def
change_page
(
self
,
page_to_show
:
str
)
->
int
:
"""
Change the page shown in page_stack.
"""
self
.
widgets
.
page_stack
.
setCurrentWidget
(
getattr
(
self
.
widgets
,
page_to_show
))
self
.
widgets
.
expert_passlock_stack
.
setCurrentIndex
(
0
)
# reset password lock on expert settings
return
0
@
Slot
(
str
,
str
,
float
)
...
...
@@ -656,12 +715,9 @@ class NativeUI(HEVClient, QMainWindow):
logging
.
debug
(
"to MCU: cmd:
%
s"
,
cmd
)
check
=
self
.
send_cmd
(
cmdtype
=
cmdtype
,
cmd
=
cmd
,
param
=
param
)
if
check
:
print
(
"confirmed this command "
+
cmdtype
+
" "
+
cmd
)
self
.
confirmPopup
.
addConfirmation
(
cmdtype
+
" "
+
cmd
)
print
(
"added popup"
)
return
0
else
:
print
(
"failed this command "
+
cmdtype
+
" "
+
cmd
)
return
1
@
Slot
(
str
)
...
...
NativeUI/alarm_widgets/alarm_popup.py
View file @
05db8768
...
...
@@ -24,6 +24,7 @@ class AlarmWidget(QtWidgets.QWidget):
def
__init__
(
self
,
NativeUI
,
abstractAlarm
,
alarmCarrier
,
*
args
,
**
kwargs
):
super
(
AlarmWidget
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
popup_height
=
int
(
NativeUI
.
alarm_popup_width
/
10.0
)
self
.
NativeUI
=
NativeUI
self
.
alarmCarrier
=
alarmCarrier
# Needs to refer to its containing object
...
...
@@ -37,27 +38,28 @@ class AlarmWidget(QtWidgets.QWidget):
iconpath_check
=
os
.
path
.
join
(
self
.
NativeUI
.
iconpath
,
"exclamation-triangle-solid.png"
)
pixmap
=
QtGui
.
QPixmap
(
iconpath_check
)
.
scaledToHeight
(
40
)
pixmap
=
QtGui
.
QPixmap
(
iconpath_check
)
.
scaledToHeight
(
popup_height
)
iconLabel
.
setPixmap
(
pixmap
)
self
.
layout
.
addWidget
(
iconLabel
)
self
.
textLabel
=
QtWidgets
.
QLabel
()
alarmLevel
=
self
.
alarmPayload
[
"alarm_type"
]
.
replace
(
'PRIORITY_'
,
''
)
alarmLevel
=
self
.
alarmPayload
[
"alarm_type"
]
#
.replace('PRIORITY_', '')
self
.
textLabel
.
setText
(
alarmLevel
+
" - "
+
self
.
alarmPayload
[
"alarm_code"
]
self
.
alarmPayload
[
"alarm_code"
]
+
" - ("
+
alarmLevel
+
")"
)
self
.
textLabel
.
setFixedWidth
(
400
)
self
.
textLabel
.
setFixedWidth
(
NativeUI
.
alarm_popup_width
)
self
.
textLabel
.
setAlignment
(
QtCore
.
Qt
.
AlignCenter
)
self
.
textLabel
.
setFont
(
NativeUI
.
text_font
)
#self.textLabel.setStyleSheet("font-size: " + NativeUI.text_size + ";")
#
self.textLabel.setStyleSheet("font-size: " + NativeUI.text_size + ";")
self
.
layout
.
addWidget
(
self
.
textLabel
)
self
.
setFixedHeight
(
40
)
self
.
setFixedHeight
(
popup_height
)
self
.
setLayout
(
self
.
layout
)
if
self
.
alarmPayload
[
"alarm_type"
]
==
"PRIORITY_HIGH"
:
self
.
setStyleSheet
(
"background-color:red;"
)
elif
self
.
alarmPayload
[
"alarm_type"
]
==
"PRIORITY_MEDIUM"
:
self
.
setStyleSheet
(
"background-color:orange;"
)
self
.
setFixedSize
(
NativeUI
.
alarm_popup_width
+
popup_height
,
popup_height
)
# self.timer = QtCore.QTimer()
# self.timer.setInterval(500) # just faster than 60Hz
...
...
@@ -66,14 +68,13 @@ class AlarmWidget(QtWidgets.QWidget):
self
.
installEventFilter
(
self
)
def
eventFilter
(
self
,
source
,
event
):
if
(
event
.
type
()
==
QtCore
.
QEvent
.
MouseButtonPress
)
:
if
event
.
type
()
==
QtCore
.
QEvent
.
MouseButtonPress
:
self
.
NativeUI
.
widgets
.
page_buttons
.
alarms_button
.
click
()
return
False
def
get_priority
(
self
):
return
self
.
alarmPayload
[
"alarm_type"
]
def
setFont
(
self
,
font
)
->
int
:
"""
Set the font for textLabel.
...
...
@@ -95,12 +96,13 @@ class AlarmWidget(QtWidgets.QWidget):
class
AlarmPopup
(
QtWidgets
.
QDialog
):
"""Container class for alarm widgets. Handles ordering and positioning of alarms.
Needs to adjust its size whenever a widget is deleted"""
def
__init__
(
self
,
NativeUI
,
*
args
,
**
kwargs
):
super
(
AlarmPopup
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
setParent
(
NativeUI
)
# ensures popup closes when main UI does
self
.
alarmDict
=
{}
self
.
NativeUI
=
NativeUI
self
.
extraAlarms
=
AlarmExtrasWidget
(
NativeUI
,
self
)
self
.
extraAlarms
=
AlarmExtrasWidget
(
NativeUI
,
self
)
self
.
layout
=
QtWidgets
.
QVBoxLayout
()
self
.
layout
.
setSpacing
(
0
)
...
...
@@ -141,7 +143,7 @@ class AlarmPopup(QtWidgets.QDialog):
self
.
NativeUI
,
abstractAlarm
,
self
)
self
.
refresh_alarm_ordering
()
#self.layout.addWidget(self.alarmDict[abstractAlarm.alarmPayload["alarm_code"]])
#
self.layout.addWidget(self.alarmDict[abstractAlarm.alarmPayload["alarm_code"]])
return
0
def
removeAlarm
(
self
,
abstractAlarm
):
...
...
@@ -157,25 +159,26 @@ class AlarmPopup(QtWidgets.QDialog):
self
.
layout
.
removeWidget
(
self
.
alarmDict
[
key
])
for
key
in
self
.
alarmDict
:
if
self
.
alarmDict
[
key
]
.
get_priority
()
==
'PRIORITY_HIGH'
:
if
self
.
alarmDict
[
key
]
.
get_priority
()
==
"PRIORITY_HIGH"
:
if
self
.
layout
.
count
()
==
4
:
self
.
extraAlarms
.
update_text
(
1
+
len
(
self
.
alarmDict
)
-
self
.
layout
.
count
())
self
.
extraAlarms
.
update_text
(
1
+
len
(
self
.
alarmDict
)
-
self
.
layout
.
count
()
)
self
.
layout
.
addWidget
(
self
.
extraAlarms
)
break
self
.
layout
.
addWidget
(
self
.
alarmDict
[
key
])
if
self
.
layout
.
count
()
<
5
:
for
key
in
self
.
alarmDict
:
if
self
.
layout
.
count
()
==
3
:
self
.
extraAlarms
.
update_text
(
len
(
self
.
alarmDict
)
-
self
.
layout
.
count
())
self
.
extraAlarms
.
update_text
(
len
(
self
.
alarmDict
)
-
self
.
layout
.
count
()
)
self
.
layout
.
addWidget
(
self
.
extraAlarms
)
break
if
self
.
alarmDict
[
key
]
.
get_priority
()
==
'PRIORITY_LOW'
:
if
self
.
alarmDict
[
key
]
.
get_priority
()
==
"PRIORITY_LOW"
:
self
.
layout
.
addWidget
(
self
.
alarmDict
[
key
])
# def resetTimer(self, alarmPayload):
# self.alarmDict[alarmPayload["alarm_code"]].timer.start()
...
...
@@ -188,49 +191,52 @@ class AlarmPopup(QtWidgets.QDialog):
return
0
class
AlarmExtrasWidget
(
QtWidgets
.
QWidget
):
"""Object containing information particular to one alarm.
Created when alarm received from microcontroller, timeout after alarm signal stops.
Is contained within alarmPopup"""
def
__init__
(
self
,
NativeUI
,
alarmCarrier
,
*
args
,
**
kwargs
):
super
(
AlarmExtrasWidget
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
popup_height
=
int
(
NativeUI
.
alarm_popup_width
/
10.0
)
self
.
NativeUI
=
NativeUI
self
.
alarmCarrier
=
alarmCarrier
# Needs to refer to its containing object
self
.
alarmCarrier
=
alarmCarrier
# Needs to refer to its containing object
self
.
layout
=
QtWidgets
.
QHBoxLayout
()
self
.
layout
.
setSpacing
(
0
)
self
.
layout
.
setMargin
(
0
)
#self.alarmPayload = abstractAlarm.alarmPayload
#
self.alarmPayload = abstractAlarm.alarmPayload
iconLabel
=
QtWidgets
.
QLabel
()
iconpath_check
=
os
.
path
.
join
(
self
.
NativeUI
.
iconpath
,
"exclamation-triangle-solid.png"
)
pixmap
=
QtGui
.
QPixmap
(
iconpath_check
)
.
scaledToHeight
(
40
)
pixmap
=
QtGui
.
QPixmap
(
iconpath_check
)
.
scaledToHeight
(
popup_height
)
iconLabel
.
setPixmap
(
pixmap
)
self
.
layout
.
addWidget
(
iconLabel
)
self
.
textLabel
=
QtWidgets
.
QLabel
()
self
.
textLabel
.
setText
(
'1 More Alarms'
)
self
.
textLabel
.
setFixedWidth
(
400
)
self
.
textLabel
.
setText
(
"1 More Alarms"
)
self
.
textLabel
.
setFixedWidth
(
NativeUI
.
alarm_popup_width
)
self
.
textLabel
.
setAlignment
(
QtCore
.
Qt
.
AlignCenter
)
self
.
textLabel
.
setFont
(
NativeUI
.
text_font
)
#self.textLabel.setStyleSheet("font-size: " + NativeUI.text_size + ";")
#
self.textLabel.setStyleSheet("font-size: " + NativeUI.text_size + ";")
self
.
layout
.
addWidget
(
self
.
textLabel
)
self
.
setFixedHeight
(
40
)
self
.
setFixedHeight
(
popup_height
)
self
.
setLayout
(
self
.
layout
)
self
.
setStyleSheet
(
"background-color:red;"
)
#
self.priority = "PRIORITY_LOW"
#
self.priority = "PRIORITY_LOW"
self
.
installEventFilter
(
self
)
self
.
setFixedSize
(
NativeUI
.
alarm_popup_width
+
popup_height
,
popup_height
)
def
update_text
(
self
,
num
):
self
.
textLabel
.
setText
(
str
(
num
)
+
' More Alarms'
)
self
.
textLabel
.
setText
(
str
(
num
)
+
" More Alarms"
)
def
eventFilter
(
self
,
source
,
event
):
if
(
event
.
type
()
==
QtCore
.
QEvent
.
MouseButtonPress
)
:
if
event
.
type
()
==
QtCore
.
QEvent
.
MouseButtonPress
:
self
.
NativeUI
.
widgets
.
page_buttons
.
alarms_button
.
click
()
return
False
...
...
NativeUI/alarm_widgets/alarm_table.py
View file @
05db8768
...
...
@@ -19,10 +19,10 @@ from datetime import datetime
class
AlarmTable
(
QtWidgets
.
QTableWidget
):
"""Table containing all of the alarms since power up are contained. Easily sorted"""
def
__init__
(
self
,
NativeUI
,
*
args
,
**
kwargs
):
super
(
AlarmTable
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
alarmDict
=
{}
self
.
setSizePolicy
(
QtWidgets
.
QSizePolicy
.
Expanding
,
QtWidgets
.
QSizePolicy
.
Expanding
)
...
...
@@ -40,40 +40,33 @@ class AlarmTable(QtWidgets.QTableWidget):
self
.
payloadKeys
=
[
"alarm_type"
,
"alarm_code"
]
self
.
resizeColumnsToContents
()
self
.
alarmDict
=
{}
self
.
alarm
Cell
Dict
=
{}
self
.
timer
=
QtCore
.
QTimer
()
self
.
timer
.
setInterval
(
100
)
# self.timer.timeout.connect(self.updateDuration)
self
.
timer
.
start
()
def
addAlarm
(
self
,
abstractAlarm
):
timestamp
=
str
(
datetime
.
now
())[:
-
3
]
newItem
=
QtWidgets
.
QListWidgetItem
(
self
.
solidBell
,
timestamp
+
": "
+
abstractAlarm
.
alarmPayload
[
"alarm_type"
]
+
" - "
+
abstractAlarm
.
alarmPayload
[
"alarm_code"
],
)
self
.
insertItem
(
0
,
newItem
)
# add to the top
# self.labelList
# widg = self.cellWidget(rowNumber, 4)
# cellItem.setText(str(abstractAlarm.duration))
# abstractAlarm.alarmExpired.connect(lambda i =newItem, j = abstractAlarm: self.update_duration(i,j))
# self.setItem(self.nrows, colnum, newItem)
# tableItem.setText(str(abstractAlarm.duration))
def
removeAlarm
(
self
,
abstractAlarm
):
for
x
in
range
(
self
.
count
()
-
1
):
if
abstractAlarm
.
alarmPayload
[
"alarm_code"
]
in
self
.
item
(
x
)
.
text
():
self
.
takeItem
(
x
)
# def addAlarm(self, abstractAlarm):
# timestamp = str(datetime.now())[:-3]
# newItem = QtWidgets.QListWidgetItem(
# self.solidBell,
# timestamp
# + ": "
# + abstractAlarm.alarmPayload["alarm_type"]
# + " - "
# + abstractAlarm.alarmPayload["alarm_code"],
# )
# self.insertItem(0, newItem) # add to the top
# def removeAlarm(self, abstractAlarm):
# for x in range(self.count() - 1):
# if abstractAlarm.alarmPayload["alarm_code"] in self.item(x).text():
# self.takeItem(x)
def
addAlarmRow
(
self
,
abstractAlarm
):
"""Add a new row 1 cell at a time. Goes through alarm payload to fill information"""
self
.
setSortingEnabled
(
False
)
self
.
setRowCount
(
self
.
nrows
+
1
)
colnum
=
0
newItem
=
QtWidgets
.
QTableWidgetItem
(
str
(
abstractAlarm
.
startTime
)[:
-
3
])
self
.
setItem
(
self
.
nrows
,
0
,
newItem
)
...
...
@@ -85,26 +78,20 @@ class AlarmTable(QtWidgets.QTableWidget):
self
.
setItem
(
self
.
nrows
,
2
,
newItem
)
newItem
=
QtWidgets
.
QTableWidgetItem
(
" "
)
self
.
alarmDict
[
self
.
nrows
]
=
newItem
self
.
setItem
(
self
.
nrows
,
3
,
self
.
alarmDict
[
self
.
nrows
])
# abstractAlarm.alarmExpired.connect(lambda i = self.alarmDict[self.nrows], j = abstractAlarm: self.update_duration(i,j))
self
.
alarm
Cell
Dict
[
self
.
nrows
]
=
newItem
self
.
setItem
(
self
.
nrows
,
3
,
self
.
alarm
Cell
Dict
[
self
.
nrows
])
# abstractAlarm.alarmExpired.connect(lambda i = self.alarm
Cell
Dict[self.nrows], j = abstractAlarm: self.update_duration(i,j))
self
.
timer
.
timeout
.
connect
(
lambda
i
=
self
.
alarmDict
[
self
.
nrows
],
j
=
abstractAlarm
:
self
.
update_duration
(
lambda
i
=
self
.
alarm
Cell
Dict
[
self
.
nrows
],
j
=
abstractAlarm
:
self
.
update_duration
(
i
,
j
)
)
if
self
.
nrows
==
1
:
self
.
resizeColumnsToContents
()
#
if self.nrows == 1:
self
.
resizeColumnsToContents
()
self
.
nrows
=
self
.
nrows
+
1
self
.
setSortingEnabled
(
True
)
def
update_duration
(
self
,
cellItem
,
abstractAlarm
):
cellItem
.
setText
(
str
(
abstractAlarm
.
duration
))
if
__name__
==
"__main__"
:
app
=
QtWidgets
.
QApplication
(
sys
.
argv
)
widg
=
alarmList
()
widg
.
show
()
sys
.
exit
(
app
.
exec_
())
NativeUI/configs/clinical_config.json
View file @
05db8768
...
...
@@ -2,7 +2,7 @@
"settings"
:[
[[
"APNEA"
,
"ms"
,
"APNEA"
,
"SET_THRESHOLD_MIN"
,
"APNEA"
,
5
,
20
,
10
,
1
,
0
]],
[[
"Check Pressure Patient"
,
"ms"
,
"CHECK_P_PATIENT"
,
"SET_THRESHOLD_MIN"
,
"CHECK_P_PATIENT"
],[
"Check Pressure Patient"
,
"ms"
,
"CHECK_P_PATIENT"
,
"SET_THRESHOLD_MAX"
,
"CHECK_P_PATIENT"
]],
[[
"FIO2"
,
"%"
,
"HIGH_FIO2"
,
"SET_THRESHOLD_MIN"
,
"HIGH_FIO2"
,
-10
,
0
,
-5
,
0.1
,
1
],[
"Percentage O2"
,
""
,
"fiO2_percent"
,
"SET_TARGET_CURRENT"
,
"FIO2_PERCENT"
,
20
,
100
,
21
,
1
,
0
],[
"FIO2"
,
"%"
,
"HIGH_FIO2"
,
"SET_THRESHOLD_MAX"
,
"HIGH_FIO2"
,
0
,
10
,
5
,
0.1
,
1
]],
[[
"FIO2"
,
"%"
,
"HIGH_FIO2"
,
"SET_THRESHOLD_MIN"
,
"HIGH_FIO2"
,
-10
,
0
,
-5
,
1
,
0
],[
"Percentage O2"
,
""
,
"fiO2_percent"
,
"SET_TARGET_CURRENT"
,
"FIO2_PERCENT"
,
0
,
100
,
51
,
1
,
0
],[
"FIO2"
,
"%"
,
"HIGH_FIO2"
,
"SET_THRESHOLD_MAX"
,
"HIGH_FIO2"
,
0
,
10
,
5
,
1
,
0
]],
[[
"Pressure"
,
" "
,
"HIGH_PRESSURE"
,
"SET_THRESHOLD_MIN"
,
"HIGH_PRESSURE"
],[
"Inhale Pressure"
,
""
,
"inspiratory_pressure"
,
"SET_TARGET_CURRENT"
,
"INSPIRATORY_PRESSURE"
,
10
,
50
,
17
,
1
,
0
],[
"Pressure"
,
" "
,
"HIGH_PRESSURE"
,
"SET_THRESHOLD_MAX"
,
"HIGH_PRESSURE"
],[
"Pressure"
,
" "
,
"HIGH_PRESSURE"
,
"SET_THRESHOLD_MAX"
,
"HIGH_PRESSURE"
]],
[[
"Respiratory Rate"
,
" "
,
"HIGH_RR"
,
"SET_THRESHOLD_MIN"
,
"HIGH_RR"
,
-10
,
0
,
-5
,
0.1
,
1
],[
"Respiratory Rate"
,
"/min"
,
"respiratory_rate"
,
"SET_TARGET_CURRENT"
,
"RESPIRATORY_RATE"
,
10
,
20
,
15
,
0.1
,
1
],[
"Respiratory Rate"
,
" "
,
"HIGH_RR"
,
"SET_THRESHOLD_MAX"
,
"HIGH_RR"
,
0
,
10
,
5
,
0.1
,
1
]],
[[
"VTE"
,
" "
,
"HIGH_VTE"
,
"SET_THRESHOLD_MIN"
,
"HIGH_VTE"
,
-10
,
0
,
-5
,
1
,
0
],[
"Inhale Volume"
,
""
,
"volume"
,
"SET_TARGET_CURRENT"
,
"VOLUME"
,
200
,
800
,
400
,
20
,
0
],[
"VTE"
,
" "
,
"HIGH_VTE"
,
"SET_THRESHOLD_MAX"
,
"HIGH_VTE"
,
0
,
10
,
5
,
1
,
0
]],
...
...
NativeUI/configs/colors.json
View file @
05db8768
...
...
@@ -5,22 +5,22 @@
"button_background_disabled"
:[
100
,
100
,
100
],
"button_foreground_enabled"
:[
200
,
200
,
200
],
"button_foreground_disabled"
:[
30
,
30
,
30
],
"button_background_highlight"
:[
30
,
93
,
248
],
"button_foreground_highlight"
:[
200
,
200
,
200
],
"label_background"
:[
0
,
0
,
0
],
"label_foreground"
:[
200
,
200
,
200
],
"display_background"
:[
200
,
200
,
200
],
"display_foreground"
:[
0
,
0
,
0
],
"display_foreground_changed"
:[
0
,
200
,
0
],
"display_foreground_red"
:[
200
,
0
,
0
],
"plot_pressure"
:[
0
,
114
,
178
],
"plot_volume"
:[
0
,
158
,
115
],
"plot_flow"
:[
240
,
228
,
66
],
"plot_pressure_flow"
:[
230
,
159
,
0
],
"plot_flow_volume"
:[
204
,
121
,
167
],
"plot_volume_pressure"
:[
86
,
180
,
233
],
"highligh"
:[
30
,
93
,
248
],
"baby_blue"
:[
144
,
231
,
211
],
"red"
:[
200
,
0
,
0
],
"green"
:[
0
,
200
,
0
],
"pressure_plot"
:[
0
,
114
,
178
],
"volume_plot"
:[
0
,
158
,
115
],
"flow_plot"
:[
240
,
228
,
66
],
"pressure_flow_plot"
:[
230
,
159
,
0
],
"flow_volume_plot"
:[
204
,
121
,
167
],
"volume_pressure_plot"
:[
86
,
180
,
233
],
"red"
:[
255
,
0
,
0
],
"green"
:[
0
,
255
,
0
],
"baby-blue"
:[
0
,
0
,
200
]
"green"
:[
0
,
200
,
0
]
}
NativeUI/configs/mode_config.json
View file @
05db8768
...
...
@@ -7,8 +7,8 @@
[
"Exhale Trigger Sensitivity"
,
""
,
"exhale_trigger_threshold"
,
"SET_TARGET_"
,
"EXHALE_TRIGGER_THRESHOLD"
,
0
,
50
,
25
,
0.2
,
1
],
[
"Inhale Pressure"
,
""
,
"inspiratory_pressure"
,
"SET_TARGET_"
,
"INSPIRATORY_PRESSURE"
,
10
,
50
,
17
,
1
,
0
],
[
"Inhale Volume"
,
""
,
"volume"
,
"SET_TARGET_"
,
"VOLUME"
,
200
,
800
,
400
,
20
,
0
],
[
"Percentage O2"
,
""
,
"fiO2_percent"
,
"SET_TARGET_"
,
"FIO2_PERCENT"
,
20
,
100
,
21
,
1
,
0
]],
[
"Percentage O2"
,
""
,
"fiO2_percent"
,
"SET_TARGET_"
,
"FIO2_PERCENT"
,
20
,
100
,
51
,
0.1
,
1
]],
"radioSettings"
:
[
"Inhale Time"
,
"IE Ratio"
],
"enableDict"
:{
"PC/AC"
:[
1
,
1
,
0
,
1
,
1
,
0
,
1
,
0
,
1
],
"PC/AC-PRVC"
:[
1
,
1
,
1
,
0
,
1
,
0
,
1
,
1
,
1
],
"PC-PSV"
:[
1
,
1
,
1
,
0
,
1
,
0
,
1
,
0
,
1
],
"CPAP"
:[
1
,
1
,
0
,
1
,
1
,
0
,
1
,
0
,
1
]},
"mainPageSettings"
:
[
"Inhale Pressure"
,
"Respiratory Rate"
,
"Inhale Time"
,
"IE Ratio"
,
"Percentage O2"
]
"mainPageSettings"
:
[
"Inhale Pressure"
,
"Respiratory Rate"
,
"Inhale Time"
,
"IE Ratio"
,
"Percentage O2"
,
"PEEP"
]
}
\ No newline at end of file
NativeUI/global_widgets/global_send_popup.py
View file @
05db8768
...
...
@@ -30,6 +30,7 @@ class SetConfirmPopup(QtWidgets.QDialog):
"""Popup called when user wants to send new values to microcontroller.
This popup shows changes and asks for confirmation"""
# a signal for each handler, so the UI knows which values were updated
ExpertSend
=
QtCore
.
Signal
()
ModeSend
=
QtCore
.
Signal
()
PersonalSend
=
QtCore
.
Signal
()
...
...
@@ -41,6 +42,7 @@ class SetConfirmPopup(QtWidgets.QDialog):
self
.
NativeUI
=
NativeUI
self
.
handler
=
None
# list widget displays the changes to be sent to MCU in human readable way
self
.
listWidget
=
QtWidgets
.
QListWidget
()
self
.
listWidget
.
setVerticalScrollBarPolicy
(
QtCore
.
Qt
.
ScrollBarAlwaysOff
)
self
.
listWidget
.
setHorizontalScrollBarPolicy
(
QtCore
.
Qt
.
ScrollBarAlwaysOff
)
...
...
@@ -61,18 +63,19 @@ class SetConfirmPopup(QtWidgets.QDialog):
vlayout
.
addLayout
(
buttonHLayout
)
self
.
setLayout
(
vlayout
)
# self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True)
# self.setWindowOpacity(0.5)
def
populatePopup
(
self
,
handlerWidget
,
messageList
):
"""One popup is used for all the handlers. It is populated when called by a particular handler"""
self
.
handler
=
handlerWidget
self
.
clearPopup
()
self
.
listWidget
.
clear
()
if
messageList
==
[]:
messageList
=
[
"no values were set"
]
for
item
in
messageList
:
listItem
=
QtWidgets
.
QListWidgetItem
(
item
)
listItem
.
setFlags
(
QtCore
.
Qt
.
NoItemFlags
)
self
.
listWidget
.
addItem
(
listItem
)
# adjust size according to list contents
self
.
listWidget
.
setFixedHeight
(
self
.
listWidget
.
sizeHintForRow
(
0
)
*
self
.
listWidget
.
count
()
+
10
)
...
...
@@ -82,14 +85,10 @@ class SetConfirmPopup(QtWidgets.QDialog):
self
.
listWidget
.
update
()
self
.
update
()
def
clearPopup
(
self
):
self
.
listWidget
.
clear
()
self
.
commandList
=
[]
return
0
def
ok_button_pressed
(
self
):
"""Send commands when ok button is clicked"""
# self.parentTemplate.liveUpdating = True
"""Emit signal to connect with handler corresponding to editted values."""
if
self
.
handler
is
None
:
logging
.
error
(
"Popup ok_button_pressed called before popupatePopup"
)
return
1
...
...
@@ -114,6 +113,8 @@ class SetConfirmPopup(QtWidgets.QDialog):
class
confirmWidget
(
QtWidgets
.
QWidget
):
"""A widget displaying an individual command confirmation from the MCU. Is contained in confirmPopup"""
def
__init__
(
self
,
NativeUI
,
confirmMessage
,
*
args
,
**
kwargs
):
super
(
confirmWidget
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
hlayout
=
QtWidgets
.
QHBoxLayout
()
...
...
@@ -137,16 +138,18 @@ class confirmWidget(QtWidgets.QWidget):
self
.
setLayout
(
self
.
hlayout
)
self
.
setFixedHeight
(
50
)
# create timer to handle timeout
self
.
timer
=
QtCore
.
QTimer
()
self
.
timer
.
setInterval
(
10000
)
self
.
timer
.
timeout
.
connect
(
self
.
confirmTimeout
)
self
.
timer
.
start
()
def
confirmTimeout
(
self
):
"""Widget should expire after a defined time"""
self
.
parent
()
.
confirmDict
.
pop
(
self
.
confirmMessage
.
replace
(
"/"
,
"_"
)
.
replace
(
"-"
,
"_"
)
self
.
confirmMessage
.
replace
(
"/"
,
"_"
)
.
replace
(
"-"
,
"_"
)
# - and / are not used in dictionary keys
)
self
.
setParent
(
None
)
self
.
setParent
(
None
)
# delete self
class
confirmPopup
(
QtWidgets
.
QDialog
):
...
...
@@ -173,12 +176,11 @@ class confirmPopup(QtWidgets.QDialog):
)
# no window title
self
.
timer
=
QtCore
.
QTimer
()
self
.
timer
.
setInterval
(
500
)
# just faster than 60Hz
self
.
timer
.
timeout
.
connect
(
self
.
adjustSize
)
self
.
timer
.
setInterval
(
500
)
self
.
timer
.
timeout
.
connect
(
self
.
adjustSize
)
# container needs to adjust to a new number of confirmWidgets
self
.
timer
.
start
()
def
addConfirmation
(
self
,
confirmMessage
):
print
(
'adding confirmation'
)
"""Add a confirmation to the popup. Triggered when UI receives a confirmation from the microcontroller"""
self
.
confirmDict
[
confirmMessage
]
=
confirmWidget
(
self
.
NativeUI
,
confirmMessage
...
...
@@ -187,8 +189,10 @@ class confirmPopup(QtWidgets.QDialog):
return
0
def
location_on_window
(
self
):
"""Places confirmWidgets at the top center of the screen"""
screen
=
QtWidgets
.
QDesktopWidget
()
.
screenGeometry
()
# widget = self.geometry()
x
=
screen
.
width
()
-
screen
.
width
()
/
2
y
=
0
# screen.height() - widget.height()
self
.
move
(
x
,
y
)
return
0
NativeUI/global_widgets/global_typeval_popup.py
View file @
05db8768
...
...
@@ -23,6 +23,7 @@ class AbstractTypeValPopup(QtWidgets.QDialog):
"""Popup takes user input to put in spin box. """
okPressed
=
QtCore
.
Signal
(
str
)
cancelPressed
=
QtCore
.
Signal
()
correctPassword
=
QtCore
.
Signal
()
def
__init__
(
self
,
NativeUI
,
characterType
,
*
args
,
**
kwargs
):
super
()
.
__init__
(
*
args
,
**
kwargs
)
...
...
@@ -32,6 +33,8 @@ class AbstractTypeValPopup(QtWidgets.QDialog):
grid
=
QtWidgets
.
QGridLayout
()
grid
.
setSpacing
(
1
)
#self.label_text, self.min, self.max, self.initVal, self.step, self.decPlaces = 'Enter Password', 0, 10000, 0, 0, 0
self
.
setStyleSheet
(
"border-radius:4px; background-color:black"
)
self
.
characterType
=
characterType
self
.
label
=
QtWidgets
.
QLabel
()
# self.label_text)
...
...
@@ -84,24 +87,17 @@ class AbstractTypeValPopup(QtWidgets.QDialog):
self
.
numberpad
.
numberPressed
.
connect
(
self
.
handle_alphapress
)
hlayout
.
addWidget
(
self
.
lineEdit
)
# grid.addWidget(self.lineEdit, 0, 0, 1, 2)
self
.
hlayout2
=
QtWidgets
.
QHBoxLayout
()
self
.
okButton
=
OkButtonWidget
(
NativeUI
)
self
.
okButton
.
setEnabled
(
True
)
self
.
okButton
.
pressed
.
connect
(
self
.
handle_ok_press
)
self
.
hlayout2
.
addWidget
(
self
.
okButton
)
# grid.addWidget(self.okButton, 1, 0)
self
.
cancelButton
=
CancelButtonWidget
(
NativeUI
)
self
.
cancelButton
.
setEnabled
(
True
)
self
.
hlayout2
.
addWidget
(
self
.
cancelButton
)
# grid.addWidget(self.cancelButton, 1, 1)
vlayout
=
QtWidgets
.
QVBoxLayout
()
vlayout
.
addWidget
(
self
.
label
)
vlayout
.
addLayout
(
hlayout
)
...
...
@@ -112,6 +108,13 @@ class AbstractTypeValPopup(QtWidgets.QDialog):
self
.
setWindowFlags
(
QtCore
.
Qt
.
FramelessWindowHint
|
QtCore
.
Qt
.
WindowStaysOnTopHint
)
# no window title