reindent and some image tweeks

This commit is contained in:
2022-07-15 16:17:13 +02:00
parent d1653e9412
commit 079c9dbc4c
4 changed files with 3395 additions and 3316 deletions

View File

@@ -1,5 +1,7 @@
import math
import logging
_log = logging.getLogger(__name__)
import math
from time import sleep
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QPainter, QBrush, QColor, QPainterPath, QPen, QDoubleValidator
@@ -11,8 +13,6 @@ from epics.ca import pend_event
from app_utils import DeltatauMotorStatus, assert_motor_positions
Ui_MotorTweak, QWidget = loadUiType('epics_widgets/MotorTweak.ui')
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
SPMG_STOP = 0
SPMG_PAUSE = 1
SPMG_MOVE = 2
@@ -20,336 +20,340 @@ SPMG_GO = 3
class MotorTweak(QWidget, Ui_MotorTweak):
event_val = pyqtSignal(str, dict)
event_readback = pyqtSignal(str, float, dict)
event_soft_limit = pyqtSignal(str, dict)
event_high_hard_limit = pyqtSignal(str, dict)
event_low_hard_limit = pyqtSignal(str, dict)
event_axis_fault = pyqtSignal(str, dict)
event_val = pyqtSignal(str, dict)
event_readback = pyqtSignal(str, float, dict)
event_soft_limit = pyqtSignal(str, dict)
event_high_hard_limit = pyqtSignal(str, dict)
event_low_hard_limit = pyqtSignal(str, dict)
event_axis_fault = pyqtSignal(str, dict)
def __init__(self, parent=None):
super(MotorTweak, self).__init__(parent=parent)
self.setupUi(self)
self._wheel_tweaks = True
self._auto_labels = True
self._locked = False
self._label_style = 'basic'
self._templates_source = {
'basic': '<b>{short_name}</b> <font color="#080">{{rbv:.{precision}f}} {units}</font>',
'small': '<small>{short_name} <font size="small" color="#080">{{rbv:.{precision}f}} {units}</font><small>',
'2 lines': '<b>{short_name}</b><br><font size="small" color="#080">{{rbv:.{precision}f}} {units}</font>',
'busy': '<b>{short_name}</b> <font color="#080">{{rbv:.{precision}f}} {units}</font>'
}
self._templates = {}
def __init__(self, parent=None):
super(MotorTweak, self).__init__(parent=parent)
self.setupUi(self)
self._wheel_tweaks = True
self._auto_labels = True
self._locked = False
self._label_style = 'basic'
self._templates_source = {
'basic': '<b>{short_name}</b> <font color="#080">{{rbv:.{precision}f}} {units}</font>',
'small': '<small>{short_name} <font size="small" color="#080">{{rbv:.{precision}f}} {units}</font><small>',
'2 lines': '<b>{short_name}</b><br><font size="small" color="#080">{{rbv:.{precision}f}} {units}</font>',
'busy': '<b>{short_name}</b> <font color="#080">{{rbv:.{precision}f}} {units}</font>'
}
self._templates = {}
def connect_motor(self, motor_base, short_name=None, **kwargs):
m = Motor(motor_base)
m.get_position()
self._ignore_limits = m.HLM == m.LLM # if both high/low limits are equal they are meaningless
self.motor = m
if not short_name:
short_name = m.description
self.short_name = short_name
self._pvname = motor_base
def connect_motor(self, motor_base, short_name=None, **kwargs):
m = Motor(motor_base)
m.get_position()
self._ignore_limits = m.HLM == m.LLM # if both high/low limits are equal they are meaningless
self.motor = m
if not short_name:
short_name = m.description
self.short_name = short_name
self._pvname = motor_base
for attr in ['RTYP', 'JVEL', 'HLS', 'LLS', 'TWV', 'RBV', 'VAL', 'LVIO', 'HLM', 'LLM']:
# logger.debug('connecting to field {}'.format(attr))
m.PV(attr, connect=True)
for attr in ['RTYP', 'JVEL', 'HLS', 'LLS', 'TWV', 'RBV', 'VAL', 'LVIO', 'HLM', 'LLM']:
# _log.debug('connecting to field {}'.format(attr))
m.PV(attr, connect=True)
self.set_motor_validator()
self._drive_val.setText(m.get('VAL', as_string=True))
self._drive_val.returnPressed.connect(self.move_motor_to_position)
self.set_motor_validator()
self._drive_val.setText(m.get('VAL', as_string=True))
self._drive_val.returnPressed.connect(self.move_motor_to_position)
tweak_min = kwargs.get("tweak_min", 0.0001)
tweak_max = kwargs.get("tweak_max", 10.0)
self._tweak_val.setText(m.get('TWV', as_string=True))
self._tweak_val.setValidator(QDoubleValidator(tweak_min, tweak_max, 4, self._tweak_val))
self._tweak_val.editingFinished.connect(lambda m=m: m.PV('TWV').put(self._tweak_val.text()))
tweak_min = kwargs.get("tweak_min", 0.0001)
tweak_max = kwargs.get("tweak_max", 10.0)
self._tweak_val.setText(m.get('TWV', as_string=True))
self._tweak_val.setValidator(QDoubleValidator(tweak_min, tweak_max, 4, self._tweak_val))
self._tweak_val.editingFinished.connect(lambda m=m: m.PV('TWV').put(self._tweak_val.text()))
self.jog_reverse.hide()
self.jog_forward.hide()
# self.jog_forward.pressed.connect(lambda: self.jog('forward', True))
# self.jog_reverse.pressed.connect(lambda: self.jog('reverse', True))
# self.jog_forward.released.connect(lambda: self.jog('forward', False))
# self.jog_reverse.released.connect(lambda: self.jog('reverse', False))
self.jog_reverse.hide()
self.jog_forward.hide()
# self.jog_forward.pressed.connect(lambda: self.jog('forward', True))
# self.jog_reverse.pressed.connect(lambda: self.jog('reverse', True))
# self.jog_forward.released.connect(lambda: self.jog('forward', False))
# self.jog_reverse.released.connect(lambda: self.jog('reverse', False))
self.tweak_forward.clicked.connect(lambda m: self.motor.tweak('forward'))
self.tweak_reverse.clicked.connect(lambda m: self.motor.tweak('reverse'))
self.tweak_forward.clicked.connect(lambda m: self.motor.tweak('forward'))
self.tweak_reverse.clicked.connect(lambda m: self.motor.tweak('reverse'))
self.bind_wheel()
self.bind_wheel()
self.update_label_template()
m.add_callback('VAL', self.set_val)
m.add_callback('RBV', self.update_label)
m.set_callback('HLS', self.update_label)
m.set_callback('LLS', self.update_label)
self.update_label_template()
m.add_callback('VAL', self.set_val)
m.add_callback('RBV', self.update_label)
m.set_callback('HLS', self.update_label)
m.set_callback('LLS', self.update_label)
m.set_callback('VAL', self.emit_signals, {'source_field': 'VAL'})
m.set_callback('RBV', self.emit_signals, {'source_field': 'RBV'})
m.set_callback('HLS', self.emit_signals, {'source_field': 'HLS'})
m.set_callback('LLS', self.emit_signals, {'source_field': 'LLS'})
m.set_callback('LVIO', self.emit_signals, {'source_field': 'LVIO'})
m.set_callback('STAT', self.emit_signals, {'source_field': 'STAT'})
m.set_callback('VAL', self.emit_signals, {'source_field': 'VAL'})
m.set_callback('RBV', self.emit_signals, {'source_field': 'RBV'})
m.set_callback('HLS', self.emit_signals, {'source_field': 'HLS'})
m.set_callback('LLS', self.emit_signals, {'source_field': 'LLS'})
m.set_callback('LVIO', self.emit_signals, {'source_field': 'LVIO'})
m.set_callback('STAT', self.emit_signals, {'source_field': 'STAT'})
m.set_callback('HLM', self.set_motor_validator)
m.set_callback('HLM', self.set_motor_validator)
def set_val(self, **kw):
v = kw['char_value']
logger.debug('updating VAL = {}'.format(v))
self._drive_val.setText(v)
def set_val(self, **kw):
v = kw['char_value']
_log.debug('updating VAL = {}'.format(v))
self._drive_val.setText(v)
def set_motor_validator(self, **kwargs):
m = self.motor
lineedit = self._drive_val
min, max = m.PV('LLM').get(), m.PV('HLM').get()
if min == max:
min = -1e6
max = 1e6
lineedit.setValidator(QDoubleValidator(min, max, m.PV('PREC').get(), lineedit))
def set_motor_validator(self, **kwargs):
m = self.motor
lineedit = self._drive_val
min, max = m.PV('LLM').get(), m.PV('HLM').get()
if min == max:
min = -1e6
max = 1e6
lineedit.setValidator(QDoubleValidator(min, max, m.PV('PREC').get(), lineedit))
def move_relative(self, dist):
self.motor.move(dist, ignore_limits=True, relative=True)
def move_relative(self, dist):
self.motor.move(dist, ignore_limits=True, relative=True)
def is_done(self):
self.motor.refresh()
return 1 == self.motor.done_moving
def is_done(self):
self.motor.refresh()
return 1 == self.motor.done_moving
def get_position(self):
return self.motor.get_position(readback=True)
def get_position(self):
return self.motor.get_position(readback=True)
def is_homed(self):
self.motor.refresh()
status = DeltatauMotorStatus(self.motor.motor_status)
return bool(DeltatauMotorStatus.MOTOR_HAS_BEEN_HOMED & status)
def is_homed(self):
self.motor.refresh()
status = DeltatauMotorStatus(self.motor.motor_status)
return bool(DeltatauMotorStatus.MOTOR_HAS_BEEN_HOMED & status)
def move_motor_to_position(self, drive=None, wait=False, assert_position=False):
if drive is None:
drive = float(self._drive_val.text())
if assert_position:
wait=True
self.motor.move(drive, wait=wait, ignore_limits=True, relative=False)
if assert_position:
assert_motor_positions([(self.motor, drive, 0.1)], timeout=1)
def move_motor_to_position(self, drive=None, wait=False, assert_position=False):
if drive is None:
drive = float(self._drive_val.text())
if assert_position:
wait=True
self.motor.move(drive, wait=wait, ignore_limits=True, relative=False)
if assert_position:
assert_motor_positions([(self.motor, drive, 0.1)], timeout=1)
def emit_signals(self, **kw):
'''
:param kw: info about the channel {
'access': 'read-only',
'char_value': '-0.105',
'chid': 36984304,
'count': 1,
'enum_strs': None,
'ftype': 20,
'host': 'SAR-CPPM-EXPMX1.psi.ch:5064',
'lower_alarm_limit': None,
'lower_ctrl_limit': 0.0,
'lower_disp_limit': 0.0,
'lower_warning_limit': None,
'motor_field': 'RBV',
'nelm': 1,
'precision': 3,
'pvname': 'SAR-EXPMX:MOT_ROT_Y.RBV',
'read_access': True,
'severity': 0,
'source_field': 'RBV',
'status': 0,
'timestamp': 1522314072.878331,
'type': 'time_double',
'typefull': 'time_double',
'units': b'deg',
'upper_alarm_limit': None,
'upper_ctrl_limit': 0.0,
'upper_disp_limit': 0.0,
'upper_warning_limit': None,
'value': -0.105,
'write_access': False}
def emit_signals(self, **kw):
'''
:param kw: info about the channel {
'access': 'read-only',
'char_value': '-0.105',
'chid': 36984304,
'count': 1,
'enum_strs': None,
'ftype': 20,
'host': 'SAR-CPPM-EXPMX1.psi.ch:5064',
'lower_alarm_limit': None,
'lower_ctrl_limit': 0.0,
'lower_disp_limit': 0.0,
'lower_warning_limit': None,
'motor_field': 'RBV',
'nelm': 1,
'precision': 3,
'pvname': 'SAR-EXPMX:MOT_ROT_Y.RBV',
'read_access': True,
'severity': 0,
'source_field': 'RBV',
'status': 0,
'timestamp': 1522314072.878331,
'type': 'time_double',
'typefull': 'time_double',
'units': b'deg',
'upper_alarm_limit': None,
'upper_ctrl_limit': 0.0,
'upper_disp_limit': 0.0,
'upper_warning_limit': None,
'value': -0.105,
'write_access': False}
:return:
'''
field = kw['motor_field']
src = kw['source_field']
kw['alias'] = self.short_name
if field != src:
return
if field == 'VAL':
self.event_val.emit(self._pvname, kw)
elif field == 'RBV':
self.event_readback.emit(kw['alias'], kw['value'], kw)
elif field == 'LVIO':
self.event_soft_limit.emit(self._pvname, kw)
elif field == 'HLS':
self.event_high_hard_limit.emit(self._pvname, kw)
self.event_axis_fault.emit(self._pvname, kw)
elif field == 'LVIO':
self.event_low_hard_limit.emit(self._pvname, kw)
self.event_axis_fault.emit(self._pvname, kw)
elif field == 'STAT':
self.event_axis_fault.emit(self._pvname, kw)
:return:
'''
field = kw['motor_field']
src = kw['source_field']
kw['alias'] = self.short_name
if field != src:
return
if field == 'VAL':
self.event_val.emit(self._pvname, kw)
elif field == 'RBV':
self.event_readback.emit(kw['alias'], kw['value'], kw)
elif field == 'LVIO':
self.event_soft_limit.emit(self._pvname, kw)
elif field == 'HLS':
self.event_high_hard_limit.emit(self._pvname, kw)
self.event_axis_fault.emit(self._pvname, kw)
elif field == 'LVIO':
self.event_low_hard_limit.emit(self._pvname, kw)
self.event_axis_fault.emit(self._pvname, kw)
elif field == 'STAT':
self.event_axis_fault.emit(self._pvname, kw)
def update_label(self, **kwargs):
m = self.motor
self.label.setText(self._templates[self._label_style].format(rbv=m.readback))
self.jog_forward.setToolTip('jog forward at {:.3f} {}/s'.format(m.jog_speed, m.units))
self.jog_reverse.setToolTip('jog reverse at {:.3f} {}/s'.format(m.jog_speed, m.units))
self.tweak_forward.setToolTip('tweak forward by {:.3f} {}'.format(m.tweak_val, m.units))
self.tweak_reverse.setToolTip('tweak reverse by {:.3f} {}'.format(m.tweak_val, m.units))
def update_label(self, **kwargs):
m = self.motor
self.label.setText(self._templates[self._label_style].format(rbv=m.readback))
self.jog_forward.setToolTip('jog forward at {:.3f} {}/s'.format(m.jog_speed, m.units))
self.jog_reverse.setToolTip('jog reverse at {:.3f} {}/s'.format(m.jog_speed, m.units))
self.tweak_forward.setToolTip('tweak forward by {:.3f} {}'.format(m.tweak_val, m.units))
self.tweak_reverse.setToolTip('tweak reverse by {:.3f} {}'.format(m.tweak_val, m.units))
def update_jog_speed(self, event):
m = self.motor
speed = m.jog_speed
sign = math.copysign(1, event.angleDelta().y())
m.jog_speed = speed + (sign * 0.1 * speed)
self.jog_forward.setToolTip('jog forward at {:.3f} {}/s'.format(m.jog_speed, m.units))
self.jog_reverse.setToolTip('jog reverse at {:.3f} {}/s'.format(m.jog_speed, m.units))
def update_jog_speed(self, event):
m = self.motor
speed = m.jog_speed
sign = math.copysign(1, event.angleDelta().y())
m.jog_speed = speed + (sign * 0.1 * speed)
self.jog_forward.setToolTip('jog forward at {:.3f} {}/s'.format(m.jog_speed, m.units))
self.jog_reverse.setToolTip('jog reverse at {:.3f} {}/s'.format(m.jog_speed, m.units))
def tweak_event(self, event):
m = self.motor
sign = event.angleDelta().y()
if sign < 0:
m.tweak_reverse = 1
else:
m.tweak_forward = 1
def tweak_event(self, event):
m = self.motor
sign = event.angleDelta().y()
if sign < 0:
m.tweak_reverse = 1
else:
m.tweak_forward = 1
def bind_wheel(self):
self.tweak_forward.wheelEvent = self.tweak_event
self.tweak_reverse.wheelEvent = self.tweak_event
def bind_wheel(self):
self.tweak_forward.wheelEvent = self.tweak_event
self.tweak_reverse.wheelEvent = self.tweak_event
def jog(self, direction, enable):
m = self.motor
if 'forw' in direction:
m.jog_forward = int(enable)
else:
m.jog_reverse = int(enable)
def jog(self, direction, enable):
m = self.motor
if 'forw' in direction:
m.jog_forward = int(enable)
else:
m.jog_reverse = int(enable)
def contextMenuEvent(self, event):
m = self.motor
menu = QMenu(self)
menu.setTitle(self.short_name)
def contextMenuEvent(self, event):
m = self.motor
menu = QMenu(self)
menu.setTitle(self.short_name)
lockmotor = QAction('lock motor', menu, checkable=True)
lockmotor.setChecked(self._locked)
menu.addAction(lockmotor)
lockmotor = QAction('lock motor', menu, checkable=True)
lockmotor.setChecked(self._locked)
menu.addAction(lockmotor)
autolabelsAction = QAction('auto', menu, checkable=True)
autolabelsAction.setChecked(self._auto_labels)
menu.addAction(autolabelsAction)
autolabelsAction = QAction('auto', menu, checkable=True)
autolabelsAction.setChecked(self._auto_labels)
menu.addAction(autolabelsAction)
wheel_tweaks = QAction('Mouse wheel tweaks motor', menu, checkable=True)
wheel_tweaks.setChecked(self._wheel_tweaks)
menu.addAction(wheel_tweaks)
wheel_tweaks = QAction('Mouse wheel tweaks motor', menu, checkable=True)
wheel_tweaks.setChecked(self._wheel_tweaks)
menu.addAction(wheel_tweaks)
stopmotorAction = QAction('Stopped', menu, checkable=True)
stopmotorAction.setChecked(SPMG_STOP == m.stop_go)
menu.addAction(stopmotorAction)
changeprecAction = menu.addAction("Change Precision")
changejogspeedAction = menu.addAction("Jog speed {:.3f} {}/s".format(m.jog_speed, m.units))
changetweakstepAction = menu.addAction("Tweak step {:.3f} {}".format(m.tweak_val, m.units))
stopmotorAction = QAction('Stopped', menu, checkable=True)
stopmotorAction.setChecked(SPMG_STOP == m.stop_go)
menu.addAction(stopmotorAction)
changeprecAction = menu.addAction("Change Precision")
changejogspeedAction = menu.addAction("Jog speed {:.3f} {}/s".format(m.jog_speed, m.units))
changetweakstepAction = menu.addAction("Tweak step {:.3f} {}".format(m.tweak_val, m.units))
tozeroAction = menu.addAction("move to Zero")
tozeroAction = menu.addAction("move to Zero")
action = menu.exec_(self.mapToGlobal(event.pos()))
if action == lockmotor:
self._locked = not self._locked
if self._locked:
self._controlbox.setDisabled(True)
else:
self._controlbox.setDisabled(False)
elif action == changeprecAction:
name = m.NAME
prec = m.PREC
msg = 'Precision for motor {}'.format(name)
logger.debug('prec before %d', prec)
prec, ok = QInputDialog.getInt(self, msg, msg, prec, 0, 10)
logger.debug('prec after (%d) %d', ok, prec)
if ok:
self.motor.put('PREC', prec, wait=True)
action = menu.exec_(self.mapToGlobal(event.pos()))
if action == lockmotor:
self._locked = not self._locked
if self._locked:
self._controlbox.setDisabled(True)
else:
self._controlbox.setDisabled(False)
elif action == changeprecAction:
name = m.NAME
prec = m.PREC
msg = 'Precision for motor {}'.format(name)
_log.debug('prec before %d', prec)
prec, ok = QInputDialog.getInt(self, msg, msg, prec, 0, 10)
_log.debug('prec after (%d) %d', ok, prec)
if ok:
self.motor.put('PREC', prec, wait=True)
elif action == changejogspeedAction:
name = m.NAME
speed = m.jog_speed
msg = 'Jog speed for motor {}'.format(name)
speed, ok = QInputDialog.getDouble(self, msg, msg, speed, 0.01, m.slew_speed, m.precision)
if ok:
self.motor.put('JVEL', speed, wait=True)
elif action == changejogspeedAction:
name = m.NAME
speed = m.jog_speed
msg = 'Jog speed for motor {}'.format(name)
speed, ok = QInputDialog.getDouble(self, msg, msg, speed, 0.01, m.slew_speed, m.precision)
if ok:
self.motor.put('JVEL', speed, wait=True)
elif action == changetweakstepAction:
name = m.NAME
tv = m.tweak_val
msg = 'Tweak step for motor {} at {} {}'.format(name, tv, m.units)
tv, ok = QInputDialog.getDouble(self, msg, msg, tv, pow(10, -m.precision), m.slew_speed, m.precision)
if ok:
self.motor.put('TWV', tv, wait=True)
elif action == changetweakstepAction:
name = m.NAME
tv = m.tweak_val
msg = 'Tweak step for motor {} at {} {}'.format(name, tv, m.units)
tv, ok = QInputDialog.getDouble(self, msg, msg, tv, pow(10, -m.precision), m.slew_speed, m.precision)
if ok:
self.motor.put('TWV', tv, wait=True)
elif action == tozeroAction:
m.move(0.0, ignore_limits=True)
elif action == tozeroAction:
m.move(0.0, ignore_limits=True)
elif action == stopmotorAction:
self.motor.stop_go = SPMG_STOP if m.stop_go == SPMG_GO else SPMG_GO
elif action == stopmotorAction:
self.motor.stop_go = SPMG_STOP if m.stop_go == SPMG_GO else SPMG_GO
elif action == autolabelsAction:
self._auto_labels = not self._auto_labels
elif action == autolabelsAction:
self._auto_labels = not self._auto_labels
elif action == wheel_tweaks:
self._wheel_tweaks = not self._wheel_tweaks
self.bind_wheel()
elif action == wheel_tweaks:
self._wheel_tweaks = not self._wheel_tweaks
self.bind_wheel()
self.update_label_template()
self.update_label_template()
def resizeEvent(self, event):
return # FIXME disable for the time being
if not self._auto_labels:
return
def resizeEvent(self, event):
return # FIXME disable for the time being
if not self._auto_labels:
return
w, h = event.size().width(), event.size().height()
if w < 400:
self.jog_reverse.hide()
self.jog_forward.hide()
else:
self.jog_reverse.show()
self.jog_forward.show()
self.update_label()
w, h = event.size().width(), event.size().height()
if w < 400:
self.jog_reverse.hide()
self.jog_forward.hide()
else:
self.jog_reverse.show()
self.jog_forward.show()
self.update_label()
def update_label_template(self):
m = self.motor
source = self._templates_source
target = self._templates
def update_label_template(self):
m = self.motor
source = self._templates_source
target = self._templates
for k in source:
target[k] = source[k].format(
short_name=self.short_name,
precision=m.PREC,
units=m.units)
self.label.setText(target[self._label_style].format(rbv=m.readback))
for k in source:
target[k] = source[k].format(
short_name=self.short_name,
precision=m.PREC,
units=m.units)
self.label.setText(target[self._label_style].format(rbv=m.readback))
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
qp.setRenderHint(QPainter.Antialiasing)
self._draw_limits(qp)
qp.end()
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
qp.setRenderHint(QPainter.Antialiasing)
self._draw_limits(qp)
qp.end()
def _draw_limits(self, qp):
m = self.motor
width, height = self.size().width(), self.size().height()
pad = 5
rounding = 2
size = 10
if m.HLS:
x, y, w, h = width - size, pad, size, height - 2 * pad
elif m.LLS:
x, y, w, h = 0, pad, size, height - 2 * pad
else:
return
color = QColor('indianred')
qp.setBrush(QBrush(color, Qt.SolidPattern))
qp.setPen(QPen(color))
path = QPainterPath()
path.setFillRule(Qt.WindingFill)
path.addRoundedRect(x, y, w, h, rounding, rounding)
qp.drawPath(path)
def _draw_limits(self, qp):
try:
m = self.motor
except AttributeError:
_log.warning('Motor not connected')
return
width, height = self.size().width(), self.size().height()
pad = 5
rounding = 2
size = 10
if m.HLS:
x, y, w, h = width - size, pad, size, height - 2 * pad
elif m.LLS:
x, y, w, h = 0, pad, size, height - 2 * pad
else:
return
color = QColor('indianred')
qp.setBrush(QBrush(color, Qt.SolidPattern))
qp.setPen(QPen(color))
path = QPainterPath()
path.setFillRule(Qt.WindingFill)
path.addRoundedRect(x, y, w, h, rounding, rounding)
qp.drawPath(path)