15 from python_qt_binding
import loadUi
16 from python_qt_binding.QtCore
import Qt, Signal
17 from python_qt_binding.QtGui
import QFileDialog, QWidget, QIcon, QTreeWidgetItem, QColor
20 _type_order = [dict, roslaunch.core.Node, LaunchtreeRosparam, roslaunch.core.Param, LaunchtreeRemap, LaunchtreeArg, object]
23 super(LaunchtreeEntryItem, self).
__init__(*args, **kw)
26 own_type_idx = map(
lambda t: isinstance(self.instance, t), self.
_type_order).index(
True)
27 other_type_idx = map(
lambda t: isinstance(other.instance, t), self.
_type_order).index(
True)
28 if own_type_idx != other_type_idx:
29 return own_type_idx >= other_type_idx
30 return self.text(0) >= other.text(0)
32 return not self.
__ge__(other)
37 update_launch_view = Signal(object)
38 display_load_error = Signal(str, str)
41 super(LaunchtreeWidget, self).
__init__()
43 self.
_rp = rospkg.RosPack()
45 res_folder = os.path.join(self._rp.get_path(
'rqt_launchtree'),
'resource')
46 ui_file = os.path.join(res_folder,
'launchtree_widget.ui')
53 self.setObjectName(
'LaunchtreeWidget')
54 self.reload_button.setIcon(QIcon.fromTheme(
'view-refresh'))
60 self.
_icon_node = QIcon(os.path.join(res_folder,
'img/node.png'))
61 self.
_icon_param = QIcon(os.path.join(res_folder,
'img/param.png'))
62 self.
_icon_arg = QIcon(os.path.join(res_folder,
'img/arg.png'))
63 self.
_icon_remap = QIcon(os.path.join(res_folder,
'img/remap.png'))
64 self.
_icon_rosparam = QIcon(os.path.join(res_folder,
'img/rosparam_load.png'))
66 self.
_icon_warn = QIcon(os.path.join(res_folder,
'img/warn.png'))
75 self.launchfile_select.currentIndexChanged.connect(
lambda idx: self.
load_launchfile())
94 self.properties_content.setCurrentIndex(0)
95 self.main_view.setCurrentIndex(0)
105 self.launch_view.clear()
106 self.properties_content.setCurrentIndex(0)
107 self.main_view.setCurrentIndex(0)
108 filename = os.path.join(
109 self._rp.get_path(self.package_select.currentText()),
110 self.launchfile_select.currentText()
112 launchargs = roslaunch.substitution_args.resolve_args(self.args_input.text()).split(
' ')
113 if os.path.isfile(filename):
114 self.progress_bar.setRange(0,0)
116 self._load_thread.daemon =
True 117 self._load_thread.start()
124 loader.load(filename, self.
_launch_config, verbose=
False, argv=[
'',
'',
''] + launchargs)
126 except Exception
as e:
127 error_msg = re.sub(
r'(\[?(?:/\w+)+\.launch\]?)',
132 if 'arg to be set' in str(e):
133 help_msg =
'You can pass args to the root launch file by specifying them in the "args" input field, for example "arg_key:=arg_value".' 134 self.display_load_error.emit(error_msg, help_msg)
135 self.update_launch_view.emit(items)
140 for key, instance
in config_tree.items():
141 if key ==
'_root':
continue 143 i.instance = instance
144 if isinstance(i.instance, roslaunch.core.Param):
145 i.inconsistent = i.instance.inconsistent
146 if isinstance(instance, dict):
148 i.inconsistent = any(c.inconsistent
for c
in childItems)
149 i.addChildren(childItems)
150 i.instance = instance.get(
'_root', instance)
151 if isinstance(i.instance, dict):
155 i.setText(0, self.
_filename_to_label(key.split(
':')[0])
if isinstance(i.instance, LaunchtreeRosparam)
else 159 self.
_icon_node if isinstance(i.instance, roslaunch.core.Node)
else 160 self.
_icon_param if isinstance(i.instance, roslaunch.core.Param)
else 161 self.
_icon_arg if isinstance(i.instance, LaunchtreeArg)
else 162 self.
_icon_remap if isinstance(i.instance, LaunchtreeRemap)
else 163 self.
_icon_rosparam if isinstance(i.instance, LaunchtreeRosparam)
else 169 self.error_label.setText(error_msg)
170 self.help_label.setText(help_msg)
171 self.main_view.setCurrentIndex(1)
174 self.launch_view.clear()
175 self.launch_view.addTopLevelItems(items)
176 self.launch_view.sortItems(0, Qt.AscendingOrder)
178 self.progress_bar.setRange(0,1)
179 self.progress_bar.setValue(1)
188 self.package_select.clear()
190 self.package_select.setCurrentIndex(0)
193 package = self.package_select.itemText(idx)
194 folder = self._rp.get_path(package)
196 self.launchfile_select.clear()
197 self.launchfile_select.addItems(launchfiles)
201 itertools.imap(
lambda p: p.replace(path +
'/',
''),
203 itertools.chain.from_iterable(
204 itertools.imap(
lambda f:
205 map(
lambda n: os.path.join(f[0], n), f[2]),
214 if not os.path.isfile(path):
return False 215 (root, ext) = os.path.splitext(path)
216 if ext !=
'.launch':
return False 223 data = current.instance
224 if isinstance(data, dict)
and data.has_key(
'_root'):
226 if isinstance(data, roslaunch.core.Param):
227 self.properties_content.setCurrentIndex(1)
228 self.param_name.setText(data.key.split(
'/')[-1] +
':')
229 if isinstance(data.value, list):
230 self.param_value_list.clear()
231 self.param_value_list.addItems(list(str(v)
for v
in data.value))
232 self.param_value_panel.setCurrentIndex(2)
233 elif len(str(data.value)) < 100:
234 self.param_value.setText(str(data.value))
235 self.param_value_panel.setCurrentIndex(0)
237 self.param_value_long.setPlainText(str(data.value))
238 self.param_value_panel.setCurrentIndex(1)
239 elif isinstance(data, roslaunch.core.Node):
240 self.properties_content.setCurrentIndex(2)
241 self.node_package.setText(data.package)
242 self.node_type.setText(data.type)
243 self.node_namespace.setText(str(data.namespace))
244 self.node_args.setText(str(data.args))
245 self.node_args.setEnabled(data.args !=
'')
246 self.node_prefix.setText(str(data.launch_prefix)
if data.launch_prefix
is not None else '')
247 self.node_prefix.setEnabled(data.launch_prefix
is not None)
248 self.node_machine.setText(str(data.machine_name)
if data.machine_name
is not None else '')
249 self.node_machine.setEnabled(data.machine_name
is not None)
250 elif isinstance(data, LaunchtreeArg):
251 self.properties_content.setCurrentIndex(4)
252 self.arg_name.setText(data.name)
253 self.arg_value.setText(str(data.value)
if data.value
is not None else '')
254 self.arg_default.setText(str(data.default)
if data.default
is not None else '')
255 self.arg_doc.setText(str(data.doc)
if data.doc
is not None else '')
256 self.arg_value.setEnabled(data.value
is not None)
257 self.arg_default.setEnabled(
not self.arg_value.isEnabled())
258 elif isinstance(data, LaunchtreeRemap):
259 self.properties_content.setCurrentIndex(5)
260 self.remap_from.setText(data.from_topic)
261 self.remap_to.setText(data.to_topic)
262 elif isinstance(data, roslaunch.core.Machine):
263 self.properties_content.setCurrentIndex(6)
264 self.machine_address.setText(str(data.address))
265 self.machine_port.setText(str(data.ssh_port))
266 self.machine_user.setText(str(data.user)
if data.user
is not None else '')
267 self.machine_user.setEnabled(data.user
is not None)
268 self.machine_loader.setText(str(data.env_loader)
if data.env_loader
is not None else '')
269 self.machine_loader.setEnabled(data.env_loader
is not None)
270 elif isinstance(data, LaunchtreeRosparam):
271 self.properties_content.setCurrentIndex(3)
272 path_segments = self.launch_view.currentItem().text(0).split(self.
_launch_separator)
273 if len(path_segments) == 2:
274 (p, l) = path_segments
275 (d, f) = os.path.split(l)
279 self.file_package.setText(p
if p
is not None else '')
280 self.file_package.setEnabled(p
is not None)
281 self.file_name.setText(f)
282 elif isinstance(data, dict):
283 self.properties_content.setCurrentIndex(3)
285 (d, f) = os.path.split(l)
286 self.file_package.setText(p)
287 self.file_name.setText(f)
291 self.properties_content.setCurrentIndex(0)
294 show_nodes = self.filter_nodes.isChecked()
295 show_params = self.filter_params.isChecked()
296 show_args = self.filter_args.isChecked()
297 show_remaps = self.filter_remaps.isChecked()
298 show_empty = self.filter_empty.isChecked()
299 search_text = self.search_input.text()
300 highlight = search_text !=
'' 301 expand =
not collapse
and highlight
303 def filter_launch_entry(entry):
307 if isinstance(entry.instance, roslaunch.core.Param):
310 elif isinstance(entry.instance, roslaunch.core.Node):
313 elif isinstance(entry.instance, roslaunch.core.Machine):
316 elif isinstance(entry.instance, LaunchtreeArg):
319 elif isinstance(entry.instance, LaunchtreeRemap):
322 show &= search_text
in entry.text(0)
326 if entry.childCount() > 0:
327 not_empty = any(map(filter_launch_entry, map(entry.child, range(entry.childCount()))))
328 show |= show_empty
or not_empty
329 entry.setExpanded(
not collapse
and (expand
or entry.isExpanded()))
331 entry.setHidden(
not show)
334 for idx
in range(self.launch_view.topLevelItemCount()):
335 filter_launch_entry(self.launch_view.topLevelItem(idx))
340 filename = os.path.join(self._rp.get_path(p), l)
341 thread = threading.Thread(target=os.system, args=[
'%s %s' % (self.
editor, filename)])
346 filename = os.path.join(
347 self._rp.get_path(self.package_select.currentText()),
348 self.launchfile_select.currentText()
350 thread = threading.Thread(target=os.system, args=[
'%s %s' % (self.
editor, filename)])
360 for d
in reversed(filename.split(
'/')):
361 if d
in self._rp_package_list:
362 return '%s%s%s' % (d, self._launch_separator,
'/'.join(reversed(tail)))
def __init__(self, args, kw)