37 from python_qt_binding.QtCore
import (QEvent, QMargins, QObject, QSize, Qt,
39 from python_qt_binding.QtGui
import QFont, QIcon
40 from python_qt_binding.QtWidgets
import (QFormLayout, QGroupBox,
41 QHBoxLayout, QLabel, QPushButton,
42 QTabWidget, QVBoxLayout, QWidget)
44 from rqt_reconfigure
import logging
48 BooleanEditor, DoubleEditor, EDITOR_TYPES, EditorWidget, EnumEditor,
49 IntegerEditor, StringEditor
54 'collapse':
'CollapseGroup',
57 'apply':
'ApplyGroup',
63 (Ze'ev) reaaaaallly cryptic function which returns the config object for 67 for k, v
in config.items():
69 if k.lower() == name.lower():
77 except Exception
as exc:
79 except AttributeError:
81 except Exception
as exc:
88 (Isaac's guess as of 12/13/2012) 89 This class bonds multiple Editor instances that are associated with 90 a single node as a group. 94 sig_node_disabled_selected = Signal(str)
95 sig_node_state_change = Signal(bool)
100 :type config: Dictionary? defined in dynamic_reconfigure.client.Client 113 verticalLayout = QVBoxLayout(self)
114 verticalLayout.setContentsMargins(QMargins(0, 0, 0, 0))
116 _widget_nodeheader = QWidget()
117 _h_layout_nodeheader = QHBoxLayout(_widget_nodeheader)
118 _h_layout_nodeheader.setContentsMargins(QMargins(0, 0, 0, 0))
121 font = QFont(
'Trebuchet MS, Bold')
122 font.setUnderline(
True)
126 _icon_disable_node = QIcon.fromTheme(
'window-close')
127 _bt_disable_node = QPushButton(_icon_disable_node,
'', self)
128 _bt_disable_node.setToolTip(
'Hide this node')
129 _bt_disable_node_size = QSize(36, 24)
130 _bt_disable_node.setFixedSize(_bt_disable_node_size)
134 _h_layout_nodeheader.addWidget(_bt_disable_node)
136 self.nodename_qlabel.setAlignment(Qt.AlignCenter)
137 font.setPointSize(10)
138 self.nodename_qlabel.setFont(font)
139 grid_widget = QWidget(self)
140 self.
grid = QFormLayout(grid_widget)
141 verticalLayout.addWidget(_widget_nodeheader)
142 verticalLayout.addWidget(grid_widget, 1)
155 logging.debug(
'Groups node name={}'.format(nodename))
156 self.nodename_qlabel.setText(nodename)
170 for param
in config[
'parameters']:
171 begin = time.time() * 1000
172 editor_type =
'(none)' 174 if param[
'edit_method']:
175 widget = EnumEditor(self.updater, param)
176 elif param[
'type']
in EDITOR_TYPES:
177 logging.debug(
'GroupWidget i_debug={} param type ={}'.format(
178 i_debug, param[
'type']))
179 editor_type = EDITOR_TYPES[param[
'type']]
180 widget = eval(editor_type)(self.updater, param)
182 self.editor_widgets.append(widget)
183 self._param_names.append(param[
'name'])
186 'groups._create_node_widgets num editors={}'.format(i_debug))
188 end = time.time() * 1000
189 time_elap = end - begin
190 logging.debug(
'ParamG editor={} loop=#{} Time={}msec'.format(
191 editor_type, i_debug, time_elap))
194 for name, group
in sorted(config[
'groups'].items()):
195 if group[
'type'] ==
'tab':
197 self, self.updater, group, self._toplevel_treenode_name)
198 elif group[
'type']
in _GROUP_TYPES.keys():
199 widget = eval(_GROUP_TYPES[group[
'type']])(
200 self.updater, group, self._toplevel_treenode_name)
202 widget = eval(_GROUP_TYPES[
''])(
203 self.updater, group, self._toplevel_treenode_name)
205 self.editor_widgets.append(widget)
206 logging.debug(
'groups._create_node_widgets name={}'.format(name))
208 for i, ed
in enumerate(self.editor_widgets):
209 ed.display(self.grid)
211 logging.debug(
'GroupWdgt._create_node_widgets' 212 ' len(editor_widgets)={}'.format(
213 len(self.editor_widgets)))
221 if 'state' in config:
222 old_state = self.
state 223 self.
state = config[
'state']
224 if self.
state != old_state:
225 self.sig_node_state_change.emit(self.
state)
227 names = [name
for name
in config.keys()]
230 if isinstance(widget, EditorWidget):
231 if widget.param_name
in names:
232 widget.update_value(config[widget.param_name])
233 elif isinstance(widget, GroupWidget):
234 cfg =
find_cfg(config, widget.param_name)
or config
235 widget.update_group(cfg)
248 logging.debug(
'param_gs _node_disable_bt_clicked')
255 super(BoxGroup, self).
__init__(updater, config, nodename)
258 self.box.setLayout(self.
grid)
261 grid.addRow(self.
box)
267 super(CollapseGroup, self).
__init__(updater, config, nodename)
268 self.box.setCheckable(
True)
269 self.box.clicked.connect(self.
click_cb)
270 self.sig_node_state_change.connect(self.box.setChecked)
272 for child
in self.box.children():
273 if child.isWidgetType():
274 self.box.toggled.connect(child.setVisible)
276 self.box.setChecked(self.
state)
279 self.updater.update({
'groups': {self.
param_name: on}})
285 super(HideGroup, self).
__init__(updater, config, nodename)
286 self.box.setVisible(self.
state)
287 self.sig_node_state_change.connect(self.box.setVisible)
292 def __init__(self, parent, updater, config, nodename):
293 super(TabGroup, self).
__init__(updater, config, nodename)
296 if not self.parent.tab_bar:
297 self.parent.tab_bar = QTabWidget()
300 self.parent.tab_bar.tabBar().installEventFilter(self)
303 self.wid.setLayout(self.
grid)
308 if event.type() == QEvent.Wheel
and not obj.hasFocus():
310 return super(GroupWidget, self).
eventFilter(obj, event)
313 if not self.parent.tab_bar_shown:
314 grid.addRow(self.parent.tab_bar)
315 self.parent.tab_bar_shown =
True 318 super(TabGroup, self).
close()
319 self.parent.tab_bar =
None 320 self.parent.tab_bar_shown =
False 326 pending_updates = Signal(bool)
335 for name, value
in config.items():
343 self.pending_updates.emit(
False)
350 self.button.clicked.connect(self.updater.apply_update)
352 self.button.setEnabled(
False)
353 self.updater.pending_updates.connect(self.
_pending_cb)
355 self.grid.addRow(self.
button)
358 if not pending_updates
and self.button.hasFocus():
361 self.button.clearFocus()
362 self.button.setEnabled(pending_updates)