def _keyframeRecorded(self): item = QTreeWidgetItem() title = "(#{}) ".format(self.playbackTree.topLevelItemCount()) + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) item.setText(0, title) self.playbackTree.addTopLevelItem(item) self.playbackTree.scrollToItem(item) self.keyframeCount.setText("{} keyframe(s) recorded".format(self.playbackTree.topLevelItemCount()))
def on_search_result(self, search_text, found, path, index, linenr, line): ''' Slot to handle the signals for search result. This signals are forwarded used search_result_signal. ''' if found and search_text == self.current_search_text: id = "%d:%s" % (index, path) self.search_results_fileset.add(path) item = (search_text, found, path, index) if item not in self.search_results: self.search_results.append((id, search_text, found, path, index, linenr, line)) if self._wait_for_result: self._search_result_index += 1 if index >= self._tabwidget.currentWidget().textCursor().position() or self._tabwidget.currentWidget().filename != path: self._wait_for_result = False self.search_result_signal.emit(search_text, found, path, index) self.replace_button.setEnabled(True) pkg, rpath = package_name(os.path.dirname(path)) itemstr = '%s [%s]' % (os.path.basename(path), pkg) if not self.found_files_list.findItems(itemstr, Qt.MatchExactly): list_item = QTreeWidgetItem(self.found_files_list) list_item.setText(0, itemstr) list_item.setToolTip(0, path) self.found_files_list.insertTopLevelItem(0, list_item) self.found_files_list.expandAll() for i in range(self.found_files_list.topLevelItemCount()): top_item = self.found_files_list.topLevelItem(i) if top_item.text(0) == itemstr: sub_item_str = "%d: %s" % (linenr, line) list_item2 = QTreeWidgetItem() list_item2.setText(0, sub_item_str) list_item2.setWhatsThis(0, id) top_item.addChild(list_item2) #self.found_files_list.setVisible(len(self.search_results_fileset) > 0) self._update_label()
def _update_robot_list(self): self._widget.robot_list_tree_widget.clear() robot_list = self.teleop_app_info.robot_list for k in robot_list.values(): robot_item = QTreeWidgetItem(self._widget.robot_list_tree_widget) robot_item.setText(0, k["name"].string) self.robot_item_list[robot_item] = k
def _update_implementation_tree(self, rapp): self._widget.implementation_tree_widget.clear() self.selected_impl = None self.impls = {} for impl in rapp['implementations']: impl_item = QTreeWidgetItem( self._widget.implementation_tree_widget) impl_item.setText(0, impl) self.impls[impl_item] = impl
def _keyframeRecorded(self): item = QTreeWidgetItem() title = "(#{}) ".format( self.playbackTree.topLevelItemCount()) + time.strftime( '%Y-%m-%d %H:%M:%S', time.localtime(time.time())) item.setText(0, title) self.playbackTree.addTopLevelItem(item) self.playbackTree.scrollToItem(item) self.keyframeCount.setText("{} keyframe(s) recorded".format( self.playbackTree.topLevelItemCount()))
def _refresh_resource_list(self, resource_list): self._lock.acquire() self.resource_list_tree_widget.clear() self.resource_item_list = {} for r in resource_list: uri = rocon_uri.parse(r) resource_item = QTreeWidgetItem(self.resource_list_tree_widget) resource_item.setText(0, uri.name.string) self.resource_item_list[resource_item] = r self._lock.release()
def on_call_service_button_clicked(self): self.response_tree_widget.clear() request = self._service_info['service_class']._request_class() self.fill_message_slots(request, self._service_info['service_name'], self._service_info['expressions'], self._service_info['counter']) try: response = self._service_info['service_proxy'](request) except rospy.ServiceException as e: qWarning( 'ServiceCaller.on_call_service_button_clicked(): request:\n%r' % (request)) qWarning( 'ServiceCaller.on_call_service_button_clicked(): error calling service "%s":\n%s' % (self._service_info['service_name'], e)) top_level_item = QTreeWidgetItem() top_level_item.setText(self._column_index['service'], 'ERROR') top_level_item.setText(self._column_index['type'], 'rospy.ServiceException') top_level_item.setText(self._column_index['expression'], str(e)) else: #qDebug('ServiceCaller.on_call_service_button_clicked(): response: %r' % (response)) top_level_item = self._recursive_create_widget_items( None, '/', response._type, response, is_editable=False) self.response_tree_widget.addTopLevelItem(top_level_item) # resize columns self.response_tree_widget.expandAll() for i in range(self.response_tree_widget.columnCount()): self.response_tree_widget.resizeColumnToContents(i)
def _on_plans(self, msg): if self._plans == msg.plans: return self._plans = msg.plans mission_tree = self._widget.findChild(QTreeWidget, "missionTreeWidget") mission_tree.clear() contigency_combo = self._widget.findChild(QComboBox, "contigencyCombo") contigency_combo.clear() for plan in sorted(self._plans, key=lambda plan: plan.name): item = QTreeWidgetItem([plan.name]) for entry in plan.entries: contigency = entry.contigency_plan if len(contigency) == 0: contigency = "none" dist = str(entry.dist) if entry.dist != 0 else "" subitem = QTreeWidgetItem([entry.mission, str(entry.timeout.secs), contigency, entry.path, dist]) item.setFlags(item.flags() | Qt.ItemIsEditable) item.addChild(subitem) mission_tree.addTopLevelItem(item) item.setExpanded(True) if plan.name != "main": contigency_combo.addItem(plan.name) contigency_combo.addItem("none") mission_combo = self._widget.findChild(QComboBox, "missionCombo") mission_combo.clear() mission_combo.addItems(sorted(msg.available_missions))
def _recursive_create_widget_items(self, parent, topic_name, type_name, message): if parent is self.topics_tree_widget: # show full topic name with preceding namespace on toplevel item topic_text = topic_name else: topic_text = topic_name.split('/')[-1] if '[' in topic_text: topic_text = topic_text[topic_text.index('['):] item = QTreeWidgetItem(parent) item.setText(self._column_index['topic'], topic_text) item.setText(self._column_index['type'], type_name) item.setData(0, Qt.UserRole, topic_name) self._tree_items[topic_name] = item if hasattr(message, '__slots__') and hasattr(message, '_slot_types'): for slot_name, type_name in zip(message.__slots__, message._slot_types): self._recursive_create_widget_items( item, topic_name + '/' + slot_name, type_name, getattr(message, slot_name)) else: base_type_str, array_size = self._extract_array_info(type_name) try: base_instance = roslib.message.get_message_class( base_type_str)() except ValueError: base_instance = None if array_size is not None and hasattr(base_instance, '__slots__'): for index in range(array_size): self._recursive_create_widget_items( item, topic_name + '[%d]' % index, base_type_str, base_instance) return item
def __init__(self, parent=None, logger=Logger(), param=None, name=str(), namespace=str()): QTreeWidgetItem.__init__(self, parent) self.set_logger(logger) if param is not None: self.set_param(param) elif len(name) > 0: self.set_name(name) self.namespace = namespace
def _handle_operator_name_change(self, operatorName, combo): self.operatorView.clear() root = self.operatorView.invisibleRootItem() for i in range(len(self._parameter_label_list[operatorName])): # fetch types for combo box cmb = QComboBox() instance_client = rospy.ServiceProxy('/kcl_rosplan/get_current_instances', GetInstanceService) resp = instance_client(self._parameter_type_list[operatorName][i]) for instancename in resp.instances: cmb.addItem(instancename,instancename) # create row item = QTreeWidgetItem(self.operatorView) item.setText(0, self._parameter_label_list[operatorName][i]) item.setText(1, self._parameter_type_list[operatorName][i]) self.operatorView.setItemWidget(item, 2, cmb)
def _create_item(self, status, select, expand_if_error): if (status.level == DiagnosticStatus.OK): parent_node = self._ok_node elif (status.level == DiagnosticStatus.WARN): parent_node = self._warning_node elif (status.level == -1) or (status.level == 3): parent_node = self._stale_node else: # ERROR parent_node = self._error_node item = TreeItem( status, QTreeWidgetItem(parent_node, [status.name + ": " + status.message])) item.tree_node.setData(0, Qt.UserRole, item) parent_node.addChild(item.tree_node) self._name_to_item[status.name] = item parent_node.sortChildren(0, Qt.AscendingOrder) if (select): item.tree_node.setSelected(True) if (expand_if_error and (status.level > 1 or status.level == -1)): parent_node.setExpanded(True) item.mark = True return item
def __init__(self, topic="diagnostics"): super(RuntimeMonitorWidget, self).__init__() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_runtime_monitor'), 'resource', 'runtime_monitor_widget.ui') loadUi(ui_file, self) self.setObjectName('RuntimeMonitorWidget') self._mutex = threading.Lock() self._error_icon = QIcon.fromTheme('dialog-error') self._warning_icon = QIcon.fromTheme('dialog-warning') self._ok_icon = QIcon.fromTheme('dialog-information') self._stale_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Stale (0)']) self._stale_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._stale_node) self._error_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Errors (0)']) self._error_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._error_node) self._warning_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Warnings (0)']) self._warning_node.setIcon(0, self._warning_icon) self.tree_widget.addTopLevelItem(self._warning_node) self._ok_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Ok (0)']) self._ok_node.setIcon(0, self._ok_icon) self.tree_widget.addTopLevelItem(self._ok_node) self.tree_widget.itemSelectionChanged.connect(self._refresh_selection) self.keyPressEvent = self._on_key_press self._name_to_item = {} self._new_errors_callback = None self._subscriber = rospy.Subscriber(topic, DiagnosticArray, self._diagnostics_callback) self._previous_ros_time = rospy.Time.now() self._timer = QTimer() self._timer.timeout.connect(self._on_timer) self._timer.start(1000) self._msg_timer = QTimer() self._msg_timer.timeout.connect(self._update_messages) self._msg_timer.start(100) self._messages = [] self._used_items = 0
def add_sensor(self, name, topic, ttype, freq): sensor = QTreeWidgetItem() sensor.setData(0, Qt.DisplayRole, name) sensor.setData(1, Qt.DisplayRole, topic) sensor.setData(2, Qt.DisplayRole, "0/" + str(freq)) sensor.setData(3, Qt.DecorationRole, self.abnormal_image) self.sensors[name] = sensor self._widget.sensor_list.addTopLevelItem(sensor) self.ts_list[name] = [] self.freq[name] = freq self.has_msg[name] = False rospy.Subscriber(topic, ttype, self.callback, (name, topic), queue_size=10)
def __init__(self, topic="diagnostics"): super(RuntimeMonitorWidget, self).__init__() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_runtime_monitor'), 'resource', 'runtime_monitor_widget.ui') loadUi(ui_file, self) self.setObjectName('RuntimeMonitorWidget') self._mutex = threading.Lock() self._error_icon = QIcon.fromTheme('dialog-error') self._warning_icon = QIcon.fromTheme('dialog-warning') self._ok_icon = QIcon.fromTheme('dialog-information') self._stale_node = QTreeWidgetItem( self.tree_widget.invisibleRootItem(), ['Stale (0)']) self._stale_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._stale_node) self._error_node = QTreeWidgetItem( self.tree_widget.invisibleRootItem(), ['Errors (0)']) self._error_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._error_node) self._warning_node = QTreeWidgetItem( self.tree_widget.invisibleRootItem(), ['Warnings (0)']) self._warning_node.setIcon(0, self._warning_icon) self.tree_widget.addTopLevelItem(self._warning_node) self._ok_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Ok (0)']) self._ok_node.setIcon(0, self._ok_icon) self.tree_widget.addTopLevelItem(self._ok_node) self.tree_widget.itemSelectionChanged.connect(self._refresh_selection) self.keyPressEvent = self._on_key_press self._name_to_item = {} self._new_errors_callback = None self._subscriber = rospy.Subscriber(topic, DiagnosticArray, self._diagnostics_callback) self._previous_ros_time = rospy.Time.now() self._timer = QTimer() self._timer.timeout.connect(self._on_timer) self._timer.start(1000) self._msg_timer = QTimer() self._msg_timer.timeout.connect(self._update_messages) self._msg_timer.start(100) self._messages = [] self._used_items = 0
def update_one_item(self, row, info): twi = QTreeWidgetItem() for col, field in enumerate(self.out_fields): val = info[field] twi.setText(col, self.format_strs[col] % val) self._table_widget.insertTopLevelItem(row, twi) for col, (key, func) in self.tooltips.iteritems(): twi.setToolTip(col, func(info[key])) with self._selected_node_lock: if twi.text(0) == self._selected_node: twi.setSelected(True) self._table_widget.setItemHidden( twi, len(self.name_filter.findall(info['node_name'])) == 0)
def update_one_item(self, row, info): twi = QTreeWidgetItem() for col, field in enumerate(self.out_fields): val = info[field] twi.setText(col, self.format_strs[col] % val) self._table_widget.insertTopLevelItem(row, twi) for col, (key, func) in self.tooltips.iteritems(): twi.setToolTip(col, func(info[key])) with self._selected_node_lock: if twi.text(0) == self._selected_node: twi.setSelected(True) self._table_widget.setItemHidden(twi, len(self.name_filter.findall(info['node_name'])) == 0)
def _update_rapp_list(self): self._widget.rapp_info_text.clear() self._widget.rapp_tree_widget.clear() self.rapps = {} rapps = self.qt_rapp_manager_info.rapps for k in rapps.values(): rapp = QTreeWidgetItem(self._widget.rapp_tree_widget) rapp.setText(0, k["name"]) self.rapps[rapp] = k self._widget.running_rapp_tree_widget.clear() rapps = self.qt_rapp_manager_info.running_rapps self._manage_buttons() for k in rapps.values(): rapp = QTreeWidgetItem(self._widget.running_rapp_tree_widget) rapp.setText(0, k["name"]) self.rapps[rapp] = k
def _update_service_list(self): self._widget.service_tree_widget.clear() self._widget.service_info_text.clear() self._widgetitem_service_pair = {} service_list = self.admin_app_interface.service_list for k in service_list.values(): # Top service service_item = QTreeWidgetItem(self._widget.service_tree_widget) # service_item=QTreeWidgetItem() service_item.setText(0, k['name']) # set Top Level Font font = service_item.font(0) font.setPointSize(20) font.setBold(True) service_item.setFont(0, font) self._widgetitem_service_pair[service_item] = k
def on_call_service_button_clicked(self): self.response_tree_widget.clear() request = self._service_info['service_class']._request_class() self.fill_message_slots(request, self._service_info['service_name'], self._service_info['expressions'], self._service_info['counter']) try: response = self._service_info['service_proxy'](request) except rospy.ServiceException as e: qWarning('ServiceCaller.on_call_service_button_clicked(): request:\n%r' % (request)) qWarning('ServiceCaller.on_call_service_button_clicked(): error calling service "%s":\n%s' % (self._service_info['service_name'], e)) top_level_item = QTreeWidgetItem() top_level_item.setText(self._column_index['service'], 'ERROR') top_level_item.setText(self._column_index['type'], 'rospy.ServiceException') top_level_item.setText(self._column_index['expression'], str(e)) else: #qDebug('ServiceCaller.on_call_service_button_clicked(): response: %r' % (response)) top_level_item = self._recursive_create_widget_items(None, '/', response._type, response, is_editable=False) self.response_tree_widget.addTopLevelItem(top_level_item) # resize columns self.response_tree_widget.expandAll() for i in range(self.response_tree_widget.columnCount()): self.response_tree_widget.resizeColumnToContents(i)
def refresh_ctrlers(self): if self.cm_namespace_combo.count() == 0: # no controller managers found so there are no controllers to update # remove old controllers for old_ctrler_name in self._ctrlers.keys(): self.remove_ctrler_from_list(old_ctrler_name) return ctrlman_ns = self.cm_namespace_combo.currentText() if self.ctrlman_ns_cur != ctrlman_ns: # new controller manager selected # remove old controllers from list from last CM for old_ctrler_name in self._ctrlers.keys(): self.remove_ctrler_from_list(old_ctrler_name) self.ctrlman_ns_cur = ctrlman_ns rospy.wait_for_service( ctrlman_ns + '/controller_manager/list_controllers', 0.2) try: resp = self.list_ctrlers[ctrlman_ns].call(ListControllersRequest()) except rospy.ServiceException as e: # TODO: display warning somehow return controller_list = resp.controller new_ctrlers = {} for c in controller_list: if c.name not in self._ctrlers: # new controller item = QTreeWidgetItem(self.ctrl_list_tree_widget) item.setData(0, Qt.UserRole, c.name) ctrler = { 'item': item, 'state': c.state, 'type': c.type, 'hw_iface': c.hardware_interface, 'resources': "[" + ", ".join(c.resources) + "]" } ctrler['item'].setText(self._column_index['name'], c.name) update_type = True update_state = True else: # controller already in list ctrler = self._ctrlers[c.name] update_type = False update_state = False if ctrler['type'] != c.type or ctrler[ 'hw_iface'] != c.hardware_interface: # total controller change ctrler['state'] = c.state ctrler['type'] = c.type ctrler['hw_iface'] = c.hardware_interface ctrler['resources'] = "[" + ", ".join(c.resources) + "]" update_type = True if ctrler['state'] != c.state: # state change ctrler['state'] = c.state update_state = True # update entries if needed if update_type: ctrler['item'].setText(self._column_index['type'], ctrler['type']) ctrler['item'].setText(self._column_index['hw_iface'], ctrler['hw_iface']) ctrler['item'].setText(self._column_index['resources'], ctrler['resources']) if update_state or update_type: ctrler['item'].setText(self._column_index['state'], ctrler['state']) new_ctrlers[c.name] = ctrler # remove missing controllers for old_ctrler_name in self._ctrlers.keys(): if old_ctrler_name not in new_ctrlers: self.remove_ctrler_from_list(old_ctrler_name) # update current controllers self._ctrlers = new_ctrlers
def _update_service_list(self): self._widget.service_tree_widget.clear() self._widget.service_info_text.clear() self._widgetitem_service_pair = {} service_list = self.admin_app_info.service_list for k in service_list.values(): #Top service service_item = QTreeWidgetItem(self._widget.service_tree_widget) #service_item=QTreeWidgetItem() service_item.setText(0, k['name']) #set Top Level Font font = service_item.font(0) font.setPointSize(20) font.setBold(True) service_item.setFont(0, font) #set client item for l in k["client_list"]: client_item = QTreeWidgetItem() client_item.setText(0, l) font = client_item.font(0) font.setPointSize(15) client_item.setFont(0, font) service_item.addChild(client_item) self._widgetitem_service_pair[service_item] = k #self._widget.service_tree_widget.addTopLevelItem(service_item) pass
def refresh_ctrlers(self): if self.cm_namespace_combo.count() == 0: # no controller managers found so there are no controllers to update # remove old controllers for old_ctrler_name in self._ctrlers.keys(): self.remove_ctrler_from_list(old_ctrler_name) return ctrlman_ns = self.cm_namespace_combo.currentText() if self.ctrlman_ns_cur != ctrlman_ns: # new controller manager selected # remove old controllers from list from last CM for old_ctrler_name in self._ctrlers.keys(): self.remove_ctrler_from_list(old_ctrler_name) self.ctrlman_ns_cur = ctrlman_ns rospy.wait_for_service(ctrlman_ns + '/controller_manager/list_controllers', 0.2) try: resp = self.list_ctrlers[ctrlman_ns].call(ListControllersRequest()) except rospy.ServiceException as e: # TODO: display warning somehow return controller_list = resp.controller new_ctrlers = {} for c in controller_list: if c.name not in self._ctrlers: # new controller item = QTreeWidgetItem(self.ctrl_list_tree_widget) item.setData(0, Qt.UserRole, c.name) ctrler = {'item' : item, 'state' : c.state, 'type' : c.type, 'hw_iface' : c.hardware_interface, 'resources' : "[" + ", ".join(c.resources) + "]"} ctrler['item'].setText(self._column_index['name'], c.name) update_type = True update_state = True else: # controller already in list ctrler = self._ctrlers[c.name] update_type = False update_state = False if ctrler['type'] != c.type or ctrler['hw_iface'] != c.hardware_interface: # total controller change ctrler['state'] = c.state ctrler['type'] = c.type ctrler['hw_iface'] = c.hardware_interface ctrler['resources'] = "[" + ", ".join(c.resources) + "]" update_type = True if ctrler['state'] != c.state: # state change ctrler['state'] = c.state update_state = True # update entries if needed if update_type: ctrler['item'].setText(self._column_index['type'], ctrler['type']) ctrler['item'].setText(self._column_index['hw_iface'], ctrler['hw_iface']) ctrler['item'].setText(self._column_index['resources'], ctrler['resources']) if update_state or update_type: ctrler['item'].setText(self._column_index['state'], ctrler['state']) new_ctrlers[c.name] = ctrler # remove missing controllers for old_ctrler_name in self._ctrlers.keys(): if old_ctrler_name not in new_ctrlers: self.remove_ctrler_from_list(old_ctrler_name) # update current controllers self._ctrlers = new_ctrlers
class RuntimeMonitorWidget(QWidget): def __init__(self, topic="diagnostics"): super(RuntimeMonitorWidget, self).__init__() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_runtime_monitor'), 'resource', 'runtime_monitor_widget.ui') loadUi(ui_file, self) self.setObjectName('RuntimeMonitorWidget') self._mutex = threading.Lock() self._error_icon = QIcon.fromTheme('dialog-error') self._warning_icon = QIcon.fromTheme('dialog-warning') self._ok_icon = QIcon.fromTheme('dialog-information') self._stale_node = QTreeWidgetItem( self.tree_widget.invisibleRootItem(), ['Stale (0)']) self._stale_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._stale_node) self._error_node = QTreeWidgetItem( self.tree_widget.invisibleRootItem(), ['Errors (0)']) self._error_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._error_node) self._warning_node = QTreeWidgetItem( self.tree_widget.invisibleRootItem(), ['Warnings (0)']) self._warning_node.setIcon(0, self._warning_icon) self.tree_widget.addTopLevelItem(self._warning_node) self._ok_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Ok (0)']) self._ok_node.setIcon(0, self._ok_icon) self.tree_widget.addTopLevelItem(self._ok_node) self.tree_widget.itemSelectionChanged.connect(self._refresh_selection) self.keyPressEvent = self._on_key_press self._name_to_item = {} self._new_errors_callback = None self._subscriber = rospy.Subscriber(topic, DiagnosticArray, self._diagnostics_callback) self._previous_ros_time = rospy.Time.now() self._timer = QTimer() self._timer.timeout.connect(self._on_timer) self._timer.start(1000) self._msg_timer = QTimer() self._msg_timer.timeout.connect(self._update_messages) self._msg_timer.start(100) self._messages = [] self._used_items = 0 def __del__(self): self.shutdown() def shutdown(self): """ Unregisters subscriber and stops timers """ self._msg_timer.stop() self._timer.stop() if rospy.is_shutdown(): return if self._subscriber: self._subscriber.unregister() self._subscriber = None def change_diagnostic_topic(self, topic): """ Changes diagnostics topic name. Must be of type diagnostic_msgs/DiagnosticArray """ if not topic: self.reset_monitor() return if self._subscriber: self._subscriber.unregister() self._subscriber = rospy.Subscriber(str(topic), DiagnosticArray, self._diagnostics_callback) self.reset_monitor() def reset_monitor(self): """ Removes all values from monitor display, resets buffers """ self._name_to_item = {} # Reset all stale topics self._messages = [] self._clear_tree() def _clear_tree(self): for index in range(self._stale_node.childCount()): self._stale_node.removeChild(self._stale_node.child(index)) for index in range(self._error_node.childCount()): self._error_node.removeChild(self._error_node.child(index)) for index in range(self._warning_node.childCount()): self._warning_node.removeChild(self._warning_node.child(index)) for index in range(self._ok_node.childCount()): self._ok_node.removeChild(self._ok_node.child(index)) self._update_root_labels() # Diagnostics callbacks (subscriber thread) def _diagnostics_callback(self, message): with self._mutex: self._messages.append(message) # Update display of messages from main thread def _update_messages(self): with self._mutex: messages = self._messages[:] self._messages = [] had_errors = False for message in messages: for status in message.status: was_selected = False if (self._name_to_item.has_key(status.name)): item = self._name_to_item[status.name] if self.tree_widget.isItemSelected(item.tree_node): was_selected = True if (item.status.level == DiagnosticStatus.ERROR and status.level != DiagnosticStatus.ERROR): had_errors = True self._update_item(item, status, was_selected) else: self._create_item(status, was_selected, True) if (status.level == DiagnosticStatus.ERROR): had_errors = True if (had_errors and self._new_errors_callback != None): self._new_errors_callback() self._update_root_labels() self.update() self._refresh_selection() def _update_item(self, item, status, was_selected): change_parent = False if (item.status.level != status.level): change_parent = True if (change_parent): if (item.status.level == DiagnosticStatus.OK): self._ok_node.removeChild(item.tree_node) elif (item.status.level == DiagnosticStatus.WARN): self._warning_node.removeChild(item.tree_node) elif (item.status.level == -1) or (item.status.level == 3): self._stale_node.removeChild(item.tree_node) else: # ERROR self._error_node.removeChild(item.tree_node) if (status.level == DiagnosticStatus.OK): parent_node = self._ok_node elif (status.level == DiagnosticStatus.WARN): parent_node = self._warning_node elif (status.level == -1) or (status.level == 3): parent_node = self._stale_node else: # ERROR parent_node = self._error_node item.tree_node.setText(0, status.name + ": " + status.message) item.tree_node.setData(0, Qt.UserRole, item) parent_node.addChild(item.tree_node) # expand errors automatically if (status.level > 1 or status.level == -1): parent_node.setExpanded(True) parent_node.sortChildren(0, Qt.AscendingOrder) if (was_selected): self.tree_widget.setCurrentItem(item.tree_node) else: item.tree_node.setText(0, status.name + ": " + status.message) item.status = status if (was_selected): self._fillout_info(item.tree_node) item.mark = True def _create_item(self, status, select, expand_if_error): if (status.level == DiagnosticStatus.OK): parent_node = self._ok_node elif (status.level == DiagnosticStatus.WARN): parent_node = self._warning_node elif (status.level == -1) or (status.level == 3): parent_node = self._stale_node else: # ERROR parent_node = self._error_node item = TreeItem( status, QTreeWidgetItem(parent_node, [status.name + ": " + status.message])) item.tree_node.setData(0, Qt.UserRole, item) parent_node.addChild(item.tree_node) self._name_to_item[status.name] = item parent_node.sortChildren(0, Qt.AscendingOrder) if (select): item.tree_node.setSelected(True) if (expand_if_error and (status.level > 1 or status.level == -1)): parent_node.setExpanded(True) item.mark = True return item def _fillout_info(self, node): item = node.data(0, Qt.UserRole) if not item: return scroll_value = self.html_browser.verticalScrollBar().value() status = item.status s = cStringIO.StringIO() s.write("<html><body>") s.write("<b>Component</b>: %s<br>\n" % (status.name)) s.write("<b>Message</b>: %s<br>\n" % (status.message)) s.write("<b>Hardware ID</b>: %s<br><br>\n\n" % (status.hardware_id)) s.write('<table border="1" cellpadding="2" cellspacing="0">') for value in status.values: value.value = value.value.replace("\n", "<br>") s.write("<tr><td><b>%s</b></td> <td>%s</td></tr>\n" % (value.key, value.value)) s.write("</table></body></html>") self.html_browser.setHtml(s.getvalue()) if self.html_browser.verticalScrollBar().maximum() < scroll_value: scroll_value = self.html_browser.verticalScrollBar().maximum() self.html_browser.verticalScrollBar().setValue(scroll_value) def _refresh_selection(self): current_item = self.tree_widget.selectedItems() if current_item: self._fillout_info(current_item[0]) def _on_key_press(self, event): key = event.key() if key == Qt.Key_Delete: nodes = self.tree_widget.selectedItems() if (nodes != [] and nodes[0] not in (self._ok_node, self._warning_node, self._stale_node, self._error_node)): item = nodes[0].data(0, Qt.UserRole) if (item.status.level == 0): self._ok_node.removeChild(item.tree_node) elif (item.status.level == 1): self._warning_node.removeChild(item.tree_node) elif (item.status.level == -1) or (item.status.level == 3): self._stale_node.removeChild(item.tree_node) else: self._error_node.removeChild(item.tree_node) del self._name_to_item[item.status.name] self._update_root_labels() self.update() event.accept() else: event.ignore() def _on_timer(self): if self._previous_ros_time + rospy.Duration(5) > rospy.Time.now(): return self._previous_ros_time = rospy.Time.now() for name, item in self._name_to_item.iteritems(): node = item.tree_node if (item != None): if (not item.mark): was_selected = False selected = self.tree_widget.selectedItems() if selected != [] and selected[0] == node: was_selected = True new_status = copy.deepcopy(item.status) new_status.level = -1 # mark stale self._update_item(item, new_status, was_selected) item.mark = False self._update_root_labels() self.update() def set_new_errors_callback(self, callback): self._new_errors_callback = callback def _update_root_labels(self): self._stale_node.setText( 0, "Stale (%s)" % (self._stale_node.childCount())) self._error_node.setText( 0, "Errors (%s)" % (self._error_node.childCount())) self._warning_node.setText( 0, "Warnings (%s)" % (self._warning_node.childCount())) self._ok_node.setText(0, "Ok (%s)" % (self._ok_node.childCount()))
def _add_msg_object(self, parent, path, name, obj, obj_type): label = name if hasattr(obj, '__slots__'): subobjs = [(slot, getattr(obj, slot)) for slot in obj.__slots__] elif type(obj) in [list, tuple]: len_obj = len(obj) if len_obj == 0: subobjs = [] else: w = int(math.ceil(math.log10(len_obj))) subobjs = [('[%*d]' % (w, i), subobj) for (i, subobj) in enumerate(obj)] else: subobjs = [] plotitem=False if type(obj) in [int, long, float]: plotitem=True if type(obj) == float: obj_repr = '%.6f' % obj else: obj_repr = str(obj) if obj_repr[0] == '-': label += ': %s' % obj_repr else: label += ': %s' % obj_repr elif type(obj) in [str, bool, int, long, float, complex, rospy.Time]: # Ignore any binary data obj_repr = codecs.utf_8_decode(str(obj), 'ignore')[0] # Truncate long representations if len(obj_repr) >= 50: obj_repr = obj_repr[:50] + '...' label += ': ' + obj_repr item = QTreeWidgetItem([label]) if name == '': pass elif path.find('.') == -1 and path.find('[') == -1: self.addTopLevelItem(item) else: parent.addChild(item) if plotitem == True: if path.replace(' ', '') in self._checked_states: item.setCheckState (0, Qt.Checked) else: item.setCheckState (0, Qt.Unchecked) item.setData(0, Qt.UserRole, (path, obj_type)) for subobj_name, subobj in subobjs: if subobj is None: continue if path == '': subpath = subobj_name # root field elif subobj_name.startswith('['): subpath = '%s%s' % (path, subobj_name) # list, dict, or tuple else: subpath = '%s.%s' % (path, subobj_name) # attribute (prefix with '.') if hasattr(subobj, '_type'): subobj_type = subobj._type else: subobj_type = type(subobj).__name__ self._add_msg_object(item, subpath, subobj_name, subobj, subobj_type)
def loadLocation(self): self.startTrajectoryButton.setEnabled(False) self.startButton.setEnabled(False) self.addButton.setEnabled(False) self.openHandButton.setEnabled(False) self.closeHandButton.setEnabled(False) self.endButton.setEnabled(False) location = self.demoLocation.text() if os.path.isdir(location): locations = [os.path.join(location, f) for f in os.listdir(location) if os.path.isfile(os.path.join(location, f)) and f.split(".")[-1] == "bag"] else: locations = [location] if len(locations) == 0 or len(locations[0]) == 0: return self.keyframeCount.setText("") self.playbackTree.clear() self.zeroMarker.clear() self._showStatus("Parsing...") totalFrames = 0 for location in sorted(locations): try: self.keyframeBagInterface = KeyframeBagInterface() parsedData = self.keyframeBagInterface.parse(location) objectsInScene = self.keyframeBagInterface.parseContainedObjects(location) except (rosbag.bag.ROSBagException, ParseException) as err: self._showStatus(str(err)) rospy.logwarn("[%s] %s", location, str(err)) self.playbackTree.clear() return totalFrames += len(parsedData) objectLabels = [] for item in objectsInScene: label = item.label if objectLabels.count(label) > 0: label = "{} #{}".format(label, objectLabels.count(label) + 1) objectLabels.append(item.label) if len(locations) > 1: self.zeroMarker.addItem(u"{} → {}".format(label, os.path.basename(location))) else: self.zeroMarker.addItem(label) items = [] for i, keyframe in enumerate(parsedData): item = QTreeWidgetItem() title = "(#{}) ".format(i) + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(keyframe["time"])) item.setText(0, title) # Add children for topic in sorted(keyframe["data"]): data = keyframe["data"][topic] topicItem = QTreeWidgetItem() topicItem.setText(0, topic) for attribute in sorted(data): attributeValueItem = QTreeWidgetItem() attributeValueItem.setText(0, attribute) attributeValueItem.setText(1, str(data[attribute])) topicItem.addChild(attributeValueItem) item.addChild(topicItem) items.append(item) if len(locations) == 1: self.playbackTree.addTopLevelItems(items) else: item = QTreeWidgetItem() item.setText(0, location) item.addChildren(items) self.playbackTree.addTopLevelItem(item) if len(locations) == 1: self.demoName.setText(os.path.basename(locations[0])) self.keyframeCount.setText("{} keyframe(s) loaded".format(totalFrames)) else: self.demoName.setText(os.path.basename(self.demoLocation.text()) + os.path.sep) self.keyframeCount.setText("{} keyframe(s) loaded from {} files".format(totalFrames, len(locations))) self._showStatus("Parsed {} keyframe(s).".format(totalFrames)) self.playDemoButton.setEnabled(True) if self.locateObjectsBox.isChecked(): self.zeroMarker.setEnabled(True)
def disp_err(self, msg): i = QTreeWidgetItem() i.setText(0, msg) self.err.addTopLevelItem(i)
def disp_warn(self,msg): i = QTreeWidgetItem() i.setText(0, msg) self.warn.addTopLevelItem(i)
def on_show_details(self): ''' Shows the subsystem in a new dialog as tree view. ''' twc = self._detailed_dialog.treewidget_components twc.clear() client_info = "OCU client: ---" if self._ocu_client is not None: add_info = '' if self.ocu_client.subsystem_restricted == self.subsystem_id: if self.ocu_client.only_monitor: add_info = ' [restricted, only monitor]' else: add_info = ' [restricted]' client_info = "OCU client: %s%s" % (self.ocu_client.address, add_info) self._detailed_dialog.label_info.setText(client_info) if self.name == self._subsystem.ident.name: for node in self._subsystem.nodes: node_item = QTreeWidgetItem(twc) node_name = node.ident.name if node.ident.name else "NODE" node_item.setText( 0, "%s [id: %d]" % (node_name, node.ident.address.node_id)) for comp in node.components: cmp_item = QTreeWidgetItem(node_item) cmp_name = self._get_component_name(comp.address) cmp_item.setText( 0, "%s [%d.%d.%d]" % (cmp_name, comp.address.subsystem_id, comp.address.node_id, comp.address.component_id)) twc.expandItem(node_item) for srv in comp.services: srv_item = QTreeWidgetItem(cmp_item) srv_item.setText( 0, "%s v%d.%d" % (srv.uri, srv.major_version, srv.minor_version)) if self._detailed_dialog.isVisible(): self._detailed_dialog.setFocus(Qt.ActiveWindowFocusReason) else: self._detailed_dialog.show()
def refresh_tree(self): self.select_tree.itemChanged.disconnect() self.select_tree.clear() for joint_name in self.joint_names: item = QTreeWidgetItem(self.select_tree) item.setText(0, joint_name) item.setCheckState(0, Qt.Unchecked) item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) for traj_name in ['position', 'velocity', 'acceleration', 'effort']: sub_item = QTreeWidgetItem(item) sub_item.setText(0, traj_name) sub_item.setCheckState(0, Qt.Unchecked) sub_item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) self.select_tree.itemChanged.connect(self.update_checkbox)
class RuntimeMonitorWidget(QWidget): def __init__(self, topic="/diagnostics"): super(RuntimeMonitorWidget, self).__init__() ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'runtime_monitor_widget.ui') loadUi(ui_file, self) self.setObjectName('RuntimeMonitorWidget') self._mutex = threading.Lock() self._error_icon = QIcon.fromTheme('dialog-error') self._warning_icon = QIcon.fromTheme('dialog-warning') self._ok_icon = QIcon.fromTheme('dialog-information') self._stale_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Stale (0)']) self._stale_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._stale_node) self._error_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Errors (0)']) self._error_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._error_node) self._warning_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Warnings (0)']) self._warning_node.setIcon(0, self._warning_icon) self.tree_widget.addTopLevelItem(self._warning_node) self._ok_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Ok (0)']) self._ok_node.setIcon(0, self._ok_icon) self.tree_widget.addTopLevelItem(self._ok_node) self.tree_widget.itemSelectionChanged.connect(self._on_item_selected) self.keyPressEvent = self._on_key_press self._name_to_item = {} self._new_errors_callback = None self._subscriber = rospy.Subscriber(topic, DiagnosticArray, self._diagnostics_callback) self._timer = QTimer() self._timer.timeout.connect(self._on_timer) self._timer.start(5000) self._messages = [] self._used_items = 0 def __del__(self): if self._subscriber is not None: self._subscriber.unregister() self._subscriber = None def shutdown(self): """ Unregisters diagnostics subscriber for clean shutdown """ if rospy.is_shutdown(): return if self._subscriber is not None: self._subscriber.unregister() self._subscriber = None def change_diagnostic_topic(self, topic): """ Changes diagnostics topic name. Must be of type diagnostic_msgs/DiagnosticArray """ if len(topic) == 0: self.reset_monitor() return if self._subscriber is not None: self._subscriber.unregister() self._subscriber = rospy.Subscriber(str(topic), DiagnosticArray, self._diagnostics_callback) self.reset_monitor() def reset_monitor(self): """ Removes all values from monitor display, resets buffers """ self._name_to_item = {} # Reset all stale topics self._messages = [] self._clear_tree() def _clear_tree(self): for index in range(self._stale_node.childCount()): self._stale_node.removeChild(self._stale_node.child(index)) for index in range(self._error_node.childCount()): self._error_node.removeChild(self._error_node.child(index)) for index in range(self._warning_node.childCount()): self._warning_node.removeChild(self._warning_node.child(index)) for index in range(self._ok_node.childCount()): self._ok_node.removeChild(self._ok_node.child(index)) self._update_root_labels() def _diagnostics_callback(self, message): with self._mutex: self._messages.append(message) self.new_message(rospy.get_rostime()) def new_message(self, stamp = None): with self._mutex: had_errors = False for message in self._messages: for status in message.status: was_selected = False had_item = False if (self._name_to_item.has_key(status.name)): item = self._name_to_item[status.name] had_item = True if self.tree_widget.selectedItems() != [] and self.tree_widget.selectedItems()[0] == item: was_selected = True if (item.status.level == 2 and status.level != 2): had_errors = True self._update_item(item, status, was_selected, stamp) else: self._create_item(status, was_selected, True, stamp) if (status.level == 2): had_errors = True self._messages = [] if (had_errors and self._new_errors_callback != None): self._new_errors_callback() self._update_root_labels() self.update() def _update_item(self, item, status, was_selected, stamp): change_parent = False if (item.status.level != status.level): change_parent = True if (change_parent): if (item.status.level == 0): self._ok_node.removeChild(item.tree_node) elif (item.status.level == 1): self._warning_node.removeChild(item.tree_node) elif (item.status.level == -1): self._stale_node.removeChild(item.tree_node) else: self._error_node.removeChild(item.tree_node) if (status.level == 0): parent_node = self._ok_node elif (status.level == 1): parent_node = self._warning_node elif (status.level == -1): parent_node = self._stale_node else: parent_node = self._error_node item.tree_node.setText(0, status.name + ": " + status.message) item.stamp = stamp item.tree_node.setData(0, Qt.UserRole, item) parent_node.addChild(item.tree_node) if (status.level > 1 or status.level == -1): parent_node.setExpanded(True) parent_node.sortChildren(0, Qt.AscendingOrder) if (was_selected): item.tree_node.setSelected(True) else: item.tree_node.setText(0, status.name + ": " + status.message) item.status = status if (was_selected): self._fillout_info(item.tree_node) item.mark = True def _create_item(self, status, select, expand_if_error, stamp): if (status.level == 0): parent_node = self._ok_node elif (status.level == 1): parent_node = self._warning_node elif (status.level == -1): parent_node = self._stale_node else: parent_node = self._error_node item = TreeItem(status, QTreeWidgetItem(parent_node, [status.name + ": " + status.message]), stamp) item.tree_node.setData(0, Qt.UserRole, item) parent_node.addChild(item.tree_node) self._name_to_item[status.name] = item parent_node.sortChildren(0, Qt.AscendingOrder) if (select): item.tree_node.setSelected(True) if (expand_if_error and (status.level > 1 or status.level == -1)): parent_node.setExpanded(True) item.mark = True return item def _fillout_info(self, node): item = node.data(0, Qt.UserRole) if (item == None): return status = item.status s = cStringIO.StringIO() s.write("<html><body>") s.write("<b>Component</b>: %s<br>\n" % (status.name)) s.write("<b>Message</b>: %s<br>\n" % (status.message)) s.write("<b>Hardware ID</b>: %s<br><br>\n\n" % (status.hardware_id)) s.write('<table border="1" cellpadding="2" cellspacing="0">') for value in status.values: value.value = value.value.replace("\n", "<br>") s.write("<tr><td><b>%s</b></td> <td>%s</td></tr>\n" % (value.key, value.value)) s.write("</table></body></html>") self.html_browser.setHtml(s.getvalue()) def _on_item_selected(self): current_item = self.tree_widget.selectedItems() if current_item is not None: self._fillout_info(current_item[0]) def _on_key_press(self, event): key = event.key() if key == Qt.Key_Delete: nodes = self.tree_widget.selectedItems() if (nodes != [] and nodes[0] not in (self._ok_node, self._warning_node, self._stale_node, self._error_node)): item = nodes[0].data(0, Qt.UserRole) if (item.status.level == 0): self._ok_node.removeChild(item.tree_node) elif (item.status.level == 1): self._warning_node.removeChild(item.tree_node) elif (item.status.level == -1): self._stale_node.removeChild(item.tree_node) else: self._error_node.removeChild(item.tree_node) del self._name_to_item[item.status.name] else: event.Skip() self._update_root_labels() self.update() def _on_timer(self ): for name, item in self._name_to_item.iteritems(): node = item.tree_node if (item != None): if (not item.mark): was_selected = False selected = self.tree_widget.selectedItems() if selected != [] and selected[0] == node: was_selected = True new_status = copy.deepcopy(item.status) new_status.level = -1 self._update_item(item, new_status, was_selected, item.stamp) item.mark = False self._update_root_labels() self.update() def set_new_errors_callback(self, callback): self._new_errors_callback = callback def get_num_errors(self): return self._error_node.childCount() + self._stale_node.childCount() def get_num_warnings(self): return self._warning_node.childCount() def get_num_ok(self): return self._ok_node.childCount() def _update_root_labels(self): self._stale_node.setText(0, "Stale (%s)" % (self._stale_node.childCount())) self._error_node.setText(0, "Errors (%s)" % (self._error_node.childCount())) self._warning_node.setText(0, "Warnings (%s)" % (self._warning_node.childCount())) self._ok_node.setText(0, "Ok (%s)" % (self._ok_node.childCount()))
def loadLocation(self): self.startTrajectoryButton.setEnabled(False) self.startButton.setEnabled(False) self.addButton.setEnabled(False) self.openHandButton.setEnabled(False) self.closeHandButton.setEnabled(False) self.endButton.setEnabled(False) location = self.demoLocation.text() if os.path.isdir(location): locations = [ os.path.join(location, f) for f in os.listdir(location) if os.path.isfile(os.path.join(location, f)) and f.split(".")[-1] == "bag" ] else: locations = [location] if len(locations) == 0 or len(locations[0]) == 0: return self.keyframeCount.setText("") self.playbackTree.clear() self.zeroMarker.clear() self._showStatus("Parsing...") totalFrames = 0 for location in sorted(locations): try: self.keyframeBagInterface = KeyframeBagInterface() parsedData = self.keyframeBagInterface.parse(location) objectsInScene = self.keyframeBagInterface.parseContainedObjects( location) except (rosbag.bag.ROSBagException, ParseException) as err: self._showStatus(str(err)) rospy.logwarn("[%s] %s", location, str(err)) self.playbackTree.clear() return totalFrames += len(parsedData) objectLabels = [] for item in objectsInScene: label = item.label if objectLabels.count(label) > 0: label = "{} #{}".format(label, objectLabels.count(label) + 1) objectLabels.append(item.label) if len(locations) > 1: self.zeroMarker.addItem(u"{} → {}".format( label, os.path.basename(location))) else: self.zeroMarker.addItem(label) items = [] for i, keyframe in enumerate(parsedData): item = QTreeWidgetItem() title = "(#{}) ".format(i) + time.strftime( '%Y-%m-%d %H:%M:%S', time.localtime(keyframe["time"])) item.setText(0, title) # Add children for topic in sorted(keyframe["data"]): data = keyframe["data"][topic] topicItem = QTreeWidgetItem() topicItem.setText(0, topic) for attribute in sorted(data): attributeValueItem = QTreeWidgetItem() attributeValueItem.setText(0, attribute) attributeValueItem.setText(1, str(data[attribute])) topicItem.addChild(attributeValueItem) item.addChild(topicItem) items.append(item) if len(locations) == 1: self.playbackTree.addTopLevelItems(items) else: item = QTreeWidgetItem() item.setText(0, location) item.addChildren(items) self.playbackTree.addTopLevelItem(item) if len(locations) == 1: self.demoName.setText(os.path.basename(locations[0])) self.keyframeCount.setText( "{} keyframe(s) loaded".format(totalFrames)) else: self.demoName.setText( os.path.basename(self.demoLocation.text()) + os.path.sep) self.keyframeCount.setText( "{} keyframe(s) loaded from {} files".format( totalFrames, len(locations))) self._showStatus("Parsed {} keyframe(s).".format(totalFrames)) self.playDemoButton.setEnabled(True) if self.locateObjectsBox.isChecked(): self.zeroMarker.setEnabled(True)
def _recursive_create_widget_items(self, parent, topic_name, type_name, message, is_editable=True): item = QTreeWidgetItem(parent) if is_editable: item.setFlags(item.flags() | Qt.ItemIsEditable) else: item.setFlags(item.flags() & (~Qt.ItemIsEditable)) if parent is None: # show full topic name with preceding namespace on toplevel item topic_text = topic_name else: topic_text = topic_name.split('/')[-1] item.setText(self._column_index['service'], topic_text) item.setText(self._column_index['type'], type_name) item.setData(0, Qt.UserRole, topic_name) if hasattr(message, '__slots__') and hasattr(message, '_slot_types'): for slot_name, type_name in zip(message.__slots__, message._slot_types): self._recursive_create_widget_items(item, topic_name + '/' + slot_name, type_name, getattr(message, slot_name), is_editable) elif type(message) in (list, tuple) and (len(message) > 0) and hasattr(message[0], '__slots__'): type_name = type_name.split('[', 1)[0] for index, slot in enumerate(message): self._recursive_create_widget_items(item, topic_name + '[%d]' % index, type_name, slot, is_editable) else: item.setText(self._column_index['expression'], repr(message)) return item
def _add_msg_object(self, parent, path, name, obj, obj_type): label = name if hasattr(obj, '__slots__'): subobjs = [(slot, getattr(obj, slot)) for slot in obj.__slots__] elif type(obj) in [list, tuple]: len_obj = len(obj) if len_obj == 0: subobjs = [] else: w = int(math.ceil(math.log10(len_obj))) subobjs = [('[%*d]' % (w, i), subobj) for (i, subobj) in enumerate(obj)] else: subobjs = [] if type(obj) in [int, long, float]: if type(obj) == float: obj_repr = '%.6f' % obj else: obj_repr = str(obj) if obj_repr[0] == '-': label += ': %s' % obj_repr else: label += ': %s' % obj_repr elif type(obj) in [str, bool, int, long, float, complex, rospy.Time]: # Ignore any binary data obj_repr = codecs.utf_8_decode(str(obj), 'ignore')[0] # Truncate long representations if len(obj_repr) >= 50: obj_repr = obj_repr[:50] + '...' label += ': ' + obj_repr item = QTreeWidgetItem([label]) if name == 'msg': pass elif path.find('.') == -1 and path.find('[') == -1: self.addTopLevelItem(item) else: parent.addChild(item) item.setData(0, Qt.UserRole, (path, obj_type)) for subobj_name, subobj in subobjs: if subobj is None: continue if path == '': subpath = subobj_name # root field elif subobj_name.startswith('['): subpath = '%s%s' % (path, subobj_name) # list, dict, or tuple else: subpath = '%s.%s' % (path, subobj_name ) # attribute (prefix with '.') if hasattr(subobj, '_type'): subobj_type = subobj._type else: subobj_type = type(subobj).__name__ self._add_msg_object(item, subpath, subobj_name, subobj, subobj_type)
class RuntimeMonitorWidget(QWidget): def __init__(self, topic="diagnostics"): super(RuntimeMonitorWidget, self).__init__() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_runtime_monitor'), 'resource', 'runtime_monitor_widget.ui') loadUi(ui_file, self) self.setObjectName('RuntimeMonitorWidget') self._mutex = threading.Lock() self._error_icon = QIcon.fromTheme('dialog-error') self._warning_icon = QIcon.fromTheme('dialog-warning') self._ok_icon = QIcon.fromTheme('dialog-information') self._stale_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Stale (0)']) self._stale_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._stale_node) self._error_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Errors (0)']) self._error_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._error_node) self._warning_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Warnings (0)']) self._warning_node.setIcon(0, self._warning_icon) self.tree_widget.addTopLevelItem(self._warning_node) self._ok_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Ok (0)']) self._ok_node.setIcon(0, self._ok_icon) self.tree_widget.addTopLevelItem(self._ok_node) self.tree_widget.itemSelectionChanged.connect(self._refresh_selection) self.keyPressEvent = self._on_key_press self._name_to_item = {} self._new_errors_callback = None self._subscriber = rospy.Subscriber(topic, DiagnosticArray, self._diagnostics_callback) self._previous_ros_time = rospy.Time.now() self._timer = QTimer() self._timer.timeout.connect(self._on_timer) self._timer.start(1000) self._msg_timer = QTimer() self._msg_timer.timeout.connect(self._update_messages) self._msg_timer.start(100) self._messages = [] self._used_items = 0 def __del__(self): self.shutdown() def shutdown(self): """ Unregisters subscriber and stops timers """ self._msg_timer.stop() self._timer.stop() if rospy.is_shutdown(): return if self._subscriber: self._subscriber.unregister() self._subscriber = None def change_diagnostic_topic(self, topic): """ Changes diagnostics topic name. Must be of type diagnostic_msgs/DiagnosticArray """ if not topic: self.reset_monitor() return if self._subscriber: self._subscriber.unregister() self._subscriber = rospy.Subscriber(str(topic), DiagnosticArray, self._diagnostics_callback) self.reset_monitor() def reset_monitor(self): """ Removes all values from monitor display, resets buffers """ self._name_to_item = {} # Reset all stale topics self._messages = [] self._clear_tree() def _clear_tree(self): for index in range(self._stale_node.childCount()): self._stale_node.removeChild(self._stale_node.child(index)) for index in range(self._error_node.childCount()): self._error_node.removeChild(self._error_node.child(index)) for index in range(self._warning_node.childCount()): self._warning_node.removeChild(self._warning_node.child(index)) for index in range(self._ok_node.childCount()): self._ok_node.removeChild(self._ok_node.child(index)) self._update_root_labels() # Diagnostics callbacks (subscriber thread) def _diagnostics_callback(self, message): with self._mutex: self._messages.append(message) # Update display of messages from main thread def _update_messages(self): with self._mutex: messages = self._messages[:] self._messages = [] had_errors = False for message in messages: for status in message.status: was_selected = False if (self._name_to_item.has_key(status.name)): item = self._name_to_item[status.name] if self.tree_widget.isItemSelected(item.tree_node): was_selected = True if (item.status.level == DiagnosticStatus.ERROR and status.level != DiagnosticStatus.ERROR): had_errors = True self._update_item(item, status, was_selected) else: self._create_item(status, was_selected, True) if (status.level == DiagnosticStatus.ERROR): had_errors = True if (had_errors and self._new_errors_callback != None): self._new_errors_callback() self._update_root_labels() self.update() self._refresh_selection() def _update_item(self, item, status, was_selected): change_parent = False if (item.status.level != status.level): change_parent = True if (change_parent): if (item.status.level == DiagnosticStatus.OK): self._ok_node.removeChild(item.tree_node) elif (item.status.level == DiagnosticStatus.WARN): self._warning_node.removeChild(item.tree_node) elif (item.status.level == -1) or (item.status.level == DiagnosticStatus.STALE): self._stale_node.removeChild(item.tree_node) else: # ERROR self._error_node.removeChild(item.tree_node) if (status.level == DiagnosticStatus.OK): parent_node = self._ok_node elif (status.level == DiagnosticStatus.WARN): parent_node = self._warning_node elif (status.level == -1) or (status.level == DiagnosticStatus.STALE): parent_node = self._stale_node else: # ERROR parent_node = self._error_node item.tree_node.setText(0, status.name + ": " + status.message) item.tree_node.setData(0, Qt.UserRole, item) parent_node.addChild(item.tree_node) # expand errors automatically if (status.level > 1 or status.level == -1): parent_node.setExpanded(True) parent_node.sortChildren(0, Qt.AscendingOrder) if (was_selected): self.tree_widget.setCurrentItem(item.tree_node) else: item.tree_node.setText(0, status.name + ": " + status.message) item.status = status if (was_selected): self._fillout_info(item.tree_node) item.mark = True def _create_item(self, status, select, expand_if_error): if (status.level == DiagnosticStatus.OK): parent_node = self._ok_node elif (status.level == DiagnosticStatus.WARN): parent_node = self._warning_node elif (status.level == -1) or (status.level == DiagnosticStatus.STALE): parent_node = self._stale_node else: # ERROR parent_node = self._error_node item = TreeItem(status, QTreeWidgetItem(parent_node, [status.name + ": " + status.message])) item.tree_node.setData(0, Qt.UserRole, item) parent_node.addChild(item.tree_node) self._name_to_item[status.name] = item parent_node.sortChildren(0, Qt.AscendingOrder) if (select): item.tree_node.setSelected(True) if (expand_if_error and (status.level > 1 or status.level == -1)): parent_node.setExpanded(True) item.mark = True return item def _fillout_info(self, node): item = node.data(0, Qt.UserRole) if not item: return scroll_value = self.html_browser.verticalScrollBar().value() status = item.status s = cStringIO.StringIO() s.write("<html><body>") s.write("<b>Component</b>: %s<br>\n" % (status.name)) s.write("<b>Message</b>: %s<br>\n" % (status.message)) s.write("<b>Hardware ID</b>: %s<br><br>\n\n" % (status.hardware_id)) s.write('<table border="1" cellpadding="2" cellspacing="0">') for value in status.values: value.value = value.value.replace("\n", "<br>") s.write("<tr><td><b>%s</b></td> <td>%s</td></tr>\n" % (value.key, value.value)) s.write("</table></body></html>") self.html_browser.setHtml(s.getvalue()) if self.html_browser.verticalScrollBar().maximum() < scroll_value: scroll_value = self.html_browser.verticalScrollBar().maximum() self.html_browser.verticalScrollBar().setValue(scroll_value) def _refresh_selection(self): current_item = self.tree_widget.selectedItems() if current_item: self._fillout_info(current_item[0]) def _on_key_press(self, event): key = event.key() if key == Qt.Key_Delete: nodes = self.tree_widget.selectedItems() if (nodes != [] and nodes[0] not in (self._ok_node, self._warning_node, self._stale_node, self._error_node)): item = nodes[0].data(0, Qt.UserRole) if (item.status.level == 0): self._ok_node.removeChild(item.tree_node) elif (item.status.level == 1): self._warning_node.removeChild(item.tree_node) elif (item.status.level == -1) or (item.status.level == DiagnosticStatus.STALE): self._stale_node.removeChild(item.tree_node) else: self._error_node.removeChild(item.tree_node) del self._name_to_item[item.status.name] self._update_root_labels() self.update() event.accept() else: event.ignore() def _on_timer(self): if self._previous_ros_time + rospy.Duration(5) > rospy.Time.now(): return self._previous_ros_time = rospy.Time.now() for name, item in self._name_to_item.iteritems(): node = item.tree_node if (item != None): if (not item.mark): was_selected = False selected = self.tree_widget.selectedItems() if selected != [] and selected[0] == node: was_selected = True new_status = copy.deepcopy(item.status) new_status.level = -1 # mark stale self._update_item(item, new_status, was_selected) item.mark = False self._update_root_labels() self.update() def set_new_errors_callback(self, callback): self._new_errors_callback = callback def _update_root_labels(self): self._stale_node.setText(0, "Stale (%s)" % (self._stale_node.childCount())) self._error_node.setText(0, "Errors (%s)" % (self._error_node.childCount())) self._warning_node.setText(0, "Warnings (%s)" % (self._warning_node.childCount())) self._ok_node.setText(0, "Ok (%s)" % (self._ok_node.childCount()))
def on_search_result(self, search_text, found, path, index, linenr, line): ''' Slot to handle the signals for search result. This signals are forwarded used search_result_signal. ''' if found and search_text == self.current_search_text: id = "%d:%s" % (index, path) self.search_results_fileset.add(path) item = (search_text, found, path, index) if item not in self.search_results: self.search_results.append( (id, search_text, found, path, index, linenr, line)) if self._wait_for_result: self._search_result_index += 1 if index >= self._tabwidget.currentWidget().textCursor( ).position() or self._tabwidget.currentWidget( ).filename != path: self._wait_for_result = False self.search_result_signal.emit(search_text, found, path, index) self.replace_button.setEnabled(True) pkg, rpath = package_name(os.path.dirname(path)) itemstr = '%s [%s]' % (os.path.basename(path), pkg) if not self.found_files_list.findItems(itemstr, Qt.MatchExactly): list_item = QTreeWidgetItem(self.found_files_list) list_item.setText(0, itemstr) list_item.setToolTip(0, path) self.found_files_list.insertTopLevelItem(0, list_item) self.found_files_list.expandAll() for i in range(self.found_files_list.topLevelItemCount()): top_item = self.found_files_list.topLevelItem(i) if top_item.text(0) == itemstr: sub_item_str = "%d: %s" % (linenr, line) list_item2 = QTreeWidgetItem() list_item2.setText(0, sub_item_str) list_item2.setWhatsThis(0, id) top_item.addChild(list_item2) #self.found_files_list.setVisible(len(self.search_results_fileset) > 0) self._update_label()
def _recursive_create_widget_items(self, parent, topic_name, type_name, message, is_editable=True): item = QTreeWidgetItem(parent) if is_editable: item.setFlags(item.flags() | Qt.ItemIsEditable) else: item.setFlags(item.flags() & (~Qt.ItemIsEditable)) if parent is None: # show full topic name with preceding namespace on toplevel item topic_text = topic_name else: topic_text = topic_name.split('/')[-1] item.setText(self._column_index['service'], topic_text) item.setText(self._column_index['type'], type_name) item.setData(0, Qt.UserRole, topic_name) if hasattr(message, '__slots__') and hasattr(message, '_slot_types'): for slot_name, type_name in zip(message.__slots__, message._slot_types): self._recursive_create_widget_items( item, topic_name + '/' + slot_name, type_name, getattr(message, slot_name), is_editable) elif type(message) in (list, tuple) and (len(message) > 0) and hasattr( message[0], '__slots__'): type_name = type_name.split('[', 1)[0] for index, slot in enumerate(message): self._recursive_create_widget_items( item, topic_name + '[%d]' % index, type_name, slot, is_editable) else: item.setText(self._column_index['expression'], repr(message)) return item
def refresh_plan(self): expanded_list = [] root = self.planView.invisibleRootItem() child_count = root.childCount() for i in range(child_count): item = root.child(i) if item.isExpanded(): expanded_list.append(item.text( self._column_index['action_id'])) self.planView.clear() for action in self._action_list: item = QTreeWidgetItem(self.planView) item.setText(self._column_index['action_id'], str(action.action_id)) item.setText(self._column_index['dispatch_time'], str(action.dispatch_time)) item.setText(self._column_index['duration'], str(action.duration)) item.setText(self._column_index['status'], self._status_list.get(str(action.action_id), "-")) action_name = '(' + action.name for keyval in action.parameters: param = QTreeWidgetItem(item) param.setText(self._column_index['action_id'], '') param.setText(self._column_index['action_name'], '- ' + keyval.key + ': ' + keyval.value) param.setText(self._column_index['dispatch_time'], '') param.setText(self._column_index['duration'], '') param.setText(self._column_index['status'], '') action_name = action_name + ' ' + keyval.value item.setText(self._column_index['action_name'], action_name + ')') if str(action.action_id) in expanded_list: item.setExpanded(True)
def refresh_tree(self): self.select_tree.itemChanged.disconnect() self.select_tree.clear() for joint_name in self.joint_names: item = QTreeWidgetItem(self.select_tree) item.setText(0, joint_name) item.setCheckState(0, Qt.Unchecked) item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) for traj_name in [ 'position', 'velocity', 'acceleration', 'effort' ]: sub_item = QTreeWidgetItem(item) sub_item.setText(0, traj_name) sub_item.setCheckState(0, Qt.Unchecked) sub_item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) self.select_tree.itemChanged.connect(self.update_checkbox)