35 from decimal
import Decimal
39 from python_qt_binding
import loadUi
40 from python_qt_binding.QtCore
import QEvent, QLocale, Signal
41 from python_qt_binding.QtGui
import QDoubleValidator, QIntValidator
42 from python_qt_binding.QtWidgets
import QMenu, QWidget
46 from rqt_reconfigure
import logging
49 'bool':
'BooleanEditor',
50 'str':
'StringEditor',
51 'int':
'IntegerEditor',
52 'double':
'DoubleEditor',
58 ui_bool = os.path.join(rp.get_path(
'rqt_reconfigure'),
'resource',
60 ui_str = os.path.join(rp.get_path(
'rqt_reconfigure'),
'resource',
62 ui_num = os.path.join(rp.get_path(
'rqt_reconfigure'),
'resource',
65 ui_enum = os.path.join(rp.get_path(
'rqt_reconfigure'),
'resource',
71 This class is abstract -- its child classes should be instantiated. 73 There exist two kinds of "update" methods: 74 - _update_paramserver for Parameter Server. 75 - update_value for the value displayed on GUI. 80 @param updater: A class that extends threading.Thread. 81 @type updater: rqt_reconfigure.param_updater.ParamUpdater 94 self.tr(
'Set to Default')
99 Update the value on Parameter Server. 107 To be implemented in subclass, but still used. 109 Update the value that's displayed on the arbitrary GUI component 110 based on user's input. 112 This method is not called from the GUI thread, so any changes to 113 QObjects will need to be done through a signal. 118 self._updater.update({self.
param_name: value})
122 Should be overridden in subclass. 124 :type grid: QFormLayout 126 self._paramname_label.setText(self.
param_name)
129 self._paramname_label.setMinimumWidth(100)
130 grid.addRow(self._paramname_label, self)
137 Should be overridden in subclass. 142 self._update_paramserver(self.param_default)
145 self.cmenu.exec_(e.globalPos())
149 _update_signal = Signal(bool)
152 super(BooleanEditor, self).
__init__(updater, config)
153 loadUi(ui_bool, self)
162 self._update_signal.connect(self._checkbox.setChecked)
169 self._update_signal.emit(value)
173 _update_signal = Signal(str)
176 super(StringEditor, self).
__init__(updater, config)
179 self._paramval_lineedit.setText(config[
'default'])
183 self._paramval_lineedit.editingFinished.connect(self.
edit_finished)
186 self._update_signal.connect(self._paramval_lineedit.setText)
189 self.cmenu.addAction(self.tr(
'Set to Empty String')
194 logging.debug(
'StringEditor update_value={}'.format(
195 value.encode(errors=
'replace').decode()))
196 self._update_signal.emit(value)
199 logging.debug(
'StringEditor edit_finished val={}'.format(
200 self._paramval_lineedit.text().encode(errors=
'replace').decode()))
208 _update_signal = Signal(int)
211 super(IntegerEditor, self).
__init__(updater, config)
217 self._min_val_label.setText(str(self.
_min))
218 self._max_val_label.setText(str(self.
_max))
219 self._slider_horizontal.setRange(self.
_min, self.
_max)
223 self._paramval_lineEdit.setValidator(QIntValidator(self.
_min,
227 self._paramval_lineEdit.setText(str(config[
'default']))
228 self._slider_horizontal.setValue(int(config[
'default']))
231 self._slider_horizontal.sliderMoved.connect(self.
_slider_moved)
234 self._paramval_lineEdit.editingFinished.connect(self.
_text_changed)
238 self._slider_horizontal.setTracking(
False)
245 self.cmenu.addAction(self.tr(
'Set to Maximum')
247 self.cmenu.addAction(self.tr(
'Set to Minimum')
251 self._slider_horizontal.installEventFilter(self)
254 if event.type() == QEvent.Wheel
and not obj.hasFocus():
256 return super(EditorWidget, self).
eventFilter(obj, event)
260 self._paramval_lineEdit.setText(str(
261 self._slider_horizontal.sliderPosition()))
275 self._update_signal.emit(int(value))
279 self._slider_horizontal.blockSignals(
True)
281 self._slider_horizontal.setValue(value)
283 self._paramval_lineEdit.setText(str(value))
284 self._slider_horizontal.blockSignals(
False)
294 _update_signal = Signal(float)
297 super(DoubleEditor, self).
__init__(updater, config)
301 if config[
'min'] != -float(
'inf'):
302 self.
_min = float(config[
'min'])
303 self._min_val_label.setText(str(self.
_min))
306 self._min_val_label.setText(
'-inf')
308 if config[
'max'] != float(
'inf'):
309 self.
_max = float(config[
'max'])
310 self._max_val_label.setText(str(self.
_max))
313 self._max_val_label.setText(
'inf')
315 if config[
'min'] != -float(
'inf')
and config[
'max'] != float(
'inf'):
319 self.
_func =
lambda x: math.atan(x)
320 self.
_ifunc =
lambda x: math.tan(x)
326 self.setDisabled(
True)
333 validator = QDoubleValidator(self.
_min, self.
_max, 8, self)
334 validator.setLocale(QLocale(QLocale.C))
335 self._paramval_lineEdit.setValidator(validator)
338 self._paramval_lineEdit.setText(str(config[
'default']))
339 self._slider_horizontal.setValue(
343 self._slider_horizontal.sliderMoved.connect(self.
_slider_moved)
346 self._paramval_lineEdit.editingFinished.connect(self.
_text_changed)
350 self._slider_horizontal.setTracking(
False)
357 self.cmenu.addAction(self.tr(
'Set to Maximum')
359 self.cmenu.addAction(self.tr(
'Set to Minimum')
361 self.cmenu.addAction(self.tr(
'Set to NaN')
365 self._slider_horizontal.installEventFilter(self)
368 if event.type() == QEvent.Wheel
and not obj.hasFocus():
370 return super(EditorWidget, self).
eventFilter(obj, event)
374 self._paramval_lineEdit.setText(
'{0:f}'.format(Decimal(str(
388 """@return: Current value in text field.""" 390 self._slider_horizontal.sliderPosition() / self.
scale 391 )
if self.
scale else 0
397 return int(round((self.
_func(value)) * self.
scale))
401 self._update_signal.emit(float(value))
405 self._slider_horizontal.blockSignals(
True)
407 if not math.isnan(value):
410 self._slider_horizontal.setValue(
413 self._paramval_lineEdit.setText(
'{0:f}'.format(Decimal(str(value))))
414 self._slider_horizontal.blockSignals(
False)
427 _update_signal = Signal(int)
428 _invalid_value_signal = Signal(str)
431 super(EnumEditor, self).
__init__(updater, config)
433 loadUi(ui_enum, self)
436 enum = eval(config[
'edit_method'])[
'enum']
438 logging.error(
'reconfig EnumEditor) Malformed enum')
442 self.
names = [item[
'name']
for item
in enum]
443 self.
values = [item[
'value']
for item
in enum]
445 items = [
'%s (%s)' % (self.
names[i], self.
values[i])
446 for i
in range(0, len(self.
names))]
449 self._combobox.addItems(items)
452 self._combobox.setCurrentIndex(self.values.index(config[
'default']))
455 self._combobox.currentIndexChanged[
'int'].connect(self.
selected)
467 self._combobox.installEventFilter(self)
470 if event.type() == QEvent.Wheel
and not obj.hasFocus():
472 return super(EditorWidget, self).
eventFilter(obj, event)
476 value = self.
values[index]
478 logging.error(
"Invalid selection '{}' for parameter '{}'".format(
479 self._combobox.itemText(index), self.
param_name))
486 index = self.values.index(value)
488 self._invalid_value_signal.emit(
'invalid ({})'.format(value))
490 self._update_signal.emit(index)
494 self._combobox.blockSignals(
True)
495 if self._combobox.count() > len(self.
values):
496 self._combobox.setItemText(len(self.
values), value)
498 self._combobox.addItem(value)
499 self._combobox.setCurrentIndex(len(self.
values))
500 self._combobox.blockSignals(
False)
504 self._combobox.blockSignals(
True)
505 self._combobox.setCurrentIndex(idx)
507 self._combobox.removeItem(len(self.
values))
508 self._combobox.blockSignals(
False)