00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 import math
00036 import os
00037 
00038 from dynamic_reconfigure.msg import Config as ConfigMsg
00039 from python_qt_binding import loadUi
00040 from python_qt_binding.QtCore import Qt, Signal
00041 from python_qt_binding.QtGui import QCheckBox, QComboBox, QDoubleValidator, QIntValidator, QHBoxLayout, QLabel, QLineEdit, QPainter, QSlider, QWidget 
00042 import rospy
00043 
00044 from .param_updater import ParamUpdater
00045 
00046 EDITOR_TYPES = {
00047     'bool': 'BooleanEditor',
00048     'str': 'StringEditor',
00049     'int': 'IntegerEditor',
00050     'double': 'DoubleEditor',
00051 }
00052 
00053 class EditorWidget(QWidget):
00054 
00055     def __init__(self, updater, config):
00056         """
00057         :param updater: 
00058         :type updater: rqt_param.ParamUpdater
00059         """
00060         
00061         super(EditorWidget, self).__init__()
00062         
00063         self.updater = updater
00064         self.name = config['name']
00065 
00066         self.old_value = None
00067 
00068     def _update(self, value):
00069         if value != self.old_value:
00070             self.update_configuration(value)
00071             self.old_value = value
00072 
00073     def update_value(self, value):
00074         pass
00075 
00076     def update_configuration(self, value):
00077         self.updater.update({self.name : value})
00078 
00079     def display(self, grid, row):
00080         """
00081         Should be overridden in subclass.
00082     
00083         :type grid: ???
00084         :type row: ???
00085         """  
00086         pass
00087 
00088     def close(self):
00089         """
00090         Should be overridden in subclass.
00091         """
00092         pass
00093 
00094 class BooleanEditor(EditorWidget):
00095     def __init__(self, updater, config): 
00096         super(BooleanEditor, self).__init__(updater, config)
00097 
00098         ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
00099                                'ui/editor_bool.ui')                
00100         loadUi(ui_file, self)  
00101         
00102         self.update_value(config['default'])
00103         self._checkbox.clicked.connect(self._update)
00104 
00105     def update_value(self, value):
00106         self._checkbox.setChecked(value)
00107 
00108     def display(self, grid, row):
00109         grid.addWidget(QLabel(self.name), row, 0, Qt.AlignRight)
00110         grid.addWidget(self, row, 1)
00111 
00112 class StringEditor(EditorWidget):
00113     def __init__(self, updater, config):
00114         super(StringEditor, self).__init__(updater, config)
00115         ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
00116                                'ui/editor_string.ui')    
00117         loadUi(ui_file, self) 
00118                 
00119         self._paramval_lineedit.editingFinished.connect(self.edit_finished)
00120 
00121     def update_value(self, value):
00122         self._paramval_lineedit.setText(value)
00123 
00124     def edit_finished(self):
00125         self._update(self._paramval_lineedit.text())
00126     
00127     def display(self, grid, row):
00128         grid.addWidget(QLabel(self.name), row, 0, Qt.AlignRight)
00129         grid.addWidget(self, row, 1)
00130 
00131 class IntegerEditor(EditorWidget):
00132     def __init__(self, updater, config):
00133         super(IntegerEditor, self).__init__(updater, config)
00134         
00135         ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
00136                                'ui/editor_number.ui')
00137         loadUi(ui_file, self) 
00138 
00139         self.min = int(config['min'])
00140         self.max = int(config['max'])
00141         self._min_val_label.setText(str(self.min))
00142         self._max_val_label.setText(str(self.max))
00143 
00144         self._slider_horizontal.setRange(self.min, self.max)
00145         self._slider_horizontal.sliderReleased.connect(self.slider_released)
00146         self._slider_horizontal.sliderMoved.connect(self.update_text)
00147         
00148         
00149         
00150         self._paramval_lineEdit.setValidator(QIntValidator(self.min,
00151                                                            self.max, self))
00152         self._paramval_lineEdit.editingFinished.connect(self.editing_finished)
00153 
00154         
00155         self._paramval_lineEdit.setText(str(config['default']))
00156         self._slider_horizontal.setSliderPosition(int(config['default']))
00157 
00158     def slider_released(self):
00159         self.update_text(self._slider_horizontal.value())
00160         self._update(self._slider_horizontal.value())
00161 
00162     def update_text(self, val):
00163         rospy.logdebug(' IntegerEditor.update_text val=%s', str(val))
00164         self._paramval_lineEdit.setText(str(val))
00165 
00166     def editing_finished(self):
00167         self._slider_horizontal.setSliderPosition(
00168                                          int(self._paramval_lineEdit.text()))
00169         self._update(int(self._paramval_lineEdit.text()))
00170 
00171     def update_value(self, val):
00172         self._slider_horizontal.setSliderPosition(int(val))
00173         self._paramval_lineEdit.setText(str(val))
00174 
00175     def display(self, grid, row):
00176         grid.addWidget(QLabel(self.name), row, 0, Qt.AlignRight)
00177         grid.addWidget(self, row, 1)
00178 
00179 class DoubleEditor(EditorWidget):
00180     def __init__(self, updater, config):
00181         super(DoubleEditor, self).__init__(updater, config)
00182         
00183         ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
00184                                'ui/editor_number.ui')                
00185         loadUi(ui_file, self) 
00186 
00187         
00188         if config['min'] != -float('inf'):
00189             self.min = float(config['min'])
00190             self._min_val_label.setText(str(self.min))
00191             self.func = lambda x: x
00192             self.ifunc = self.func
00193         else:
00194             self.min = -1e10000 
00195             self._min_val_label.setText('-inf')
00196             self.func = lambda x: math.atan(x)
00197             self.ifunc = lambda x: math.tan(x)
00198 
00199         if config['max'] != float('inf'):
00200             self.max = float(config['max'])
00201             self._max_val_label.setText(str(self.max))
00202             self.func = lambda x: x
00203             self.ifunc = self.func
00204         else:
00205             self.max = 1e10000
00206             self.max_val_label.setText('inf')
00207             self.func = lambda x: math.atan(x)
00208             self.ifunc = lambda x: math.tan(x)
00209 
00210         self.scale = (self.func(self.max) - self.func(self.min)) / 100
00211         self.offset = self.func(self.min)
00212 
00213         self._slider_horizontal.setRange(self.slider_value(self.min),
00214                                          self.slider_value(self.max))
00215         self._slider_horizontal.sliderReleased.connect(self.slider_released)
00216         self._slider_horizontal.sliderMoved.connect(self.update_text)
00217 
00218         self._paramval_lineEdit.setValidator(QDoubleValidator(
00219                                                     self.min, self.max,
00220                                                     4, self))
00221         self._paramval_lineEdit.editingFinished.connect(self.editing_finished)
00222 
00223         self._paramval_lineEdit.setText(str(config['default']))
00224         self._slider_horizontal.setSliderPosition(
00225                                      self.slider_value(config['default']))
00226 
00227     def get_value(self):
00228         return self.ifunc(self._slider_horizontal.value() * self.scale)
00229 
00230     def slider_value(self, value):
00231         return int(round((self.func(value)) / self.scale))
00232 
00233     def slider_released(self):
00234         self.update_text(self.get_value())
00235         self._update(self.get_value())
00236 
00237     def update_text(self, value):
00238         self._paramval_lineEdit.setText(str(self.get_value()))
00239 
00240     def editing_finished(self):
00241         self._slider_horizontal.setSliderPosition(
00242                                self.slider_value(float(self._paramval_lineEdit.text())))
00243         self._update(float(self._paramval_lineEdit.text()))
00244 
00245     def update_value(self, val):
00246         self._slider_horizontal.setSliderPosition(
00247                                   self.slider_value(float(val)))
00248         self._paramval_lineEdit.setText(str(val))
00249 
00250     def display(self, grid, row):
00251         grid.addWidget(QLabel(self.name), row, 0, Qt.AlignRight)
00252         grid.addWidget(self, row, 1)
00253 
00254 class EnumEditor(EditorWidget):
00255     def __init__(self, updater, config):
00256         super(EnumEditor, self).__init__(updater, config)
00257 
00258         ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
00259                                'ui/editor_enum.ui')                
00260         loadUi(ui_file, self) 
00261         
00262         try:
00263             enum = eval(config['edit_method'])['enum']
00264         except:
00265             print("Malformed enum")
00266             return
00267 
00268         self.names = [item['name'] for item in enum]
00269         self.values = [item['value'] for item in enum]
00270 
00271         items = ["%s (%s)" % (self.names[i], self.values[i]) 
00272                  for i in range(0, len(self.names))]
00273 
00274         self._combobox.addItems(items)
00275         self._combobox.currentIndexChanged['int'].connect(self.selected)
00276 
00277     def selected(self, index):
00278         self._update(self.values[index])
00279 
00280     def update_value(self, val):
00281         self._combobox.setCurrentIndex(self.values.index(val))
00282 
00283     def display(self, grid, row):
00284         grid.addWidget(QLabel(self.name), row, 0, Qt.AlignRight)
00285         grid.addWidget(self, row, 1)
00286