def __init__(self): """ Creates a new list model. """ QStandardItemModel.__init__(self) self.setColumnCount(len(ParameterModel.header)) self.setHorizontalHeaderLabels([label for label, _ in ParameterModel.header])
def __init__(self): """ Initializes the ModelLogger. """ self.__log_model = QStandardItemModel(0, 4, None) self.__log_model.setHorizontalHeaderLabels( ["type", "date", "location", "message"])
def __init__(self, parent=None, progress_queue=None, viewobj=None): ''' Creates a new list model. ''' QStandardItemModel.__init__(self, parent) self.viewobj = viewobj self.setColumnCount(len(LaunchListModel.header)) self.setHorizontalHeaderLabels( [label for label, _width in LaunchListModel.header]) self.pyqt_workaround = dict( ) # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass self.items = [] self._roots = {} self._current_path = nmdurl.nmduri() self._current_master = masteruri_from_master() self._current_master_name = '' self.ros_root_paths = {} # {url: [root pasth(str)]} self.ros_root_paths[self._current_path] = [ os.path.normpath(p) for p in os.getenv("ROS_PACKAGE_PATH").split(':') ] self._progress_queue = progress_queue nm.nmd().file.listed_path.connect(self._listed_path) nm.nmd().file.packages_available.connect(self._on_new_packages) nm.nmd().file.error.connect(self._nmd_error)
def _init_monitor_parameters(self, params_monitored, _col_names_paramtable=None): """ @type params_monitored: str[] """ self._params_monitored = params_monitored self._param_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._param_datamodel.invisibleRootItem() self._view_params.setModel(self._param_datamodel) # Names of header on the QTableView. if not _col_names_paramtable: _col_names_paramtable = [ 'Param name', 'Found on Parameter Server?' ] self._param_datamodel.setHorizontalHeaderLabels(_col_names_paramtable) self.sig_param.connect(self._update_output_parameters) param_check_thread = Thread(target=self._check_params_alive, args=(self.sig_param, self._params_monitored)) return param_check_thread
def __init__(self): super(NodeSelectorWidget, self).__init__() self.stretch = None ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ui/node_selector.ui') loadUi(ui_file, self) # Setup treeview and models self._std_model = QStandardItemModel() self._node_selector_view.setModel(self._std_model) self._rootitem = self._std_model.invisibleRootItem() self._nodes_previous = None # Calling this method updates the list of the node. # Initially done only once. self._update_nodetree() # Setting slot for when user clickes on QTreeView. selectionModel = self._node_selector_view.selectionModel() selectionModel.selectionChanged.connect(self._selection_changed_slot) #TODO(Isaac): Needs auto-update function enabled, once another function # that updates node tree with maintaining collapse/expansion # state. http://goo.gl/GuwYp can be a help. # self.timer = QTimer() # self.timer.timeout.connect(self._refresh_nodes) # self.timer.start(5000) # 5sec interval is fast enough. self._collapse_button.pressed.connect( self._node_selector_view.collapseAll) self._expand_button.pressed.connect(self._node_selector_view.expandAll)
def __init__(self): ''' Creates a new list model. ''' QStandardItemModel.__init__(self) self.setColumnCount(len(ParameterModel.header)) self.setHorizontalHeaderLabels([label for label, _ in ParameterModel.header])
def __init__(self, rocon_master_uri='localhost', host_name='localhost', with_rqt=False): self.with_rqt = with_rqt self.widget = QWidget() self.pairings_view_model = QStandardItemModel() self.interactions_view_model = QStandardItemModel() self.interactions_remocon = InteractionsRemocon( rocon_master_uri, host_name) self.interactions_remocon.connect( [self.update_group_combobox, self.refresh_grids]) self.interactions_remocon.connect( [self.update_pairings_group_combobox, self.refresh_grids]) self.default_group = "All" rospack = rospkg.RosPack() ui_file = os.path.join(rospack.get_path('rocon_remocon'), 'ui', 'interactions_chooser.ui') loadUi(ui_file, self.widget, {}) # create a few directories for caching icons and ... utils.setup_home_dirs() self._init_ui() self._init_events()
def __init__(self): ''' Creates a new list model. ''' QStandardItemModel.__init__(self) self.setColumnCount(len(ServiceModel.header)) self.setHorizontalHeaderLabels([label for label, _ in ServiceModel.header]) self.pyqt_workaround = dict() # workaround for using with PyQt: store the python object to keep the defined attributes in the ServiceItem subclass
def __init__(self): ''' Creates a new list model. ''' QStandardItemModel.__init__(self) self.setColumnCount(len(SettingsModel.header)) self.setHorizontalHeaderLabels([label for label, _ in SettingsModel.header]) self.pyqt_workaround = dict() # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass
def __init__(self, local_masteruri=None): ''' Creates a new list model. ''' QStandardItemModel.__init__(self) self.setColumnCount(len(MasterModel.header)) self._masteruri = local_masteruri self.parent_view = None self.pyqt_workaround = dict() # workaround for using with PyQt: store the python object to keep the defined attributes in the MasterItem subclass
def setData(self, index, value, role): if (index.column() == 3 and index.model().data(index.model().index(index.row(), index.column() - 2, index.parent()), Qt.DisplayRole) == "bool"): if (role == Qt.CheckStateRole): stringVal = "False" if (value == Qt.Checked): stringVal = "True" return QStandardItemModel.setData(self, index, stringVal, Qt.EditRole) return QStandardItemModel.setData(self, index, value, role)
def setData(self, index, value, role): if (index.column() == index.column() == self._column_index['expression'] and index.model().data( index.model().index( index.row(), self._column_index['type'], index.parent()), Qt.DisplayRole) == 'bool'): if role == Qt.CheckStateRole: value = str(value == Qt.Checked) return QStandardItemModel.setData(self, index, value, Qt.EditRole) return QStandardItemModel.setData(self, index, value, role)
def __init__(self, context): super(ChatbotGUI, self).__init__(context) self.setObjectName('ChatbotGUI') from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns self._widget = QWidget() ui_file = os.path.join(rospkg.RosPack().get_path('chatbot_gui'), 'resource', 'ChatbotGUI.ui') loadUi(ui_file, self._widget, {'NavViewWidget': NavViewWidget}) self._widget.setObjectName('ChatbotGUIUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) self._widget.pickDone.clicked[bool].connect(self._handle_pick_clicked) self._widget.placeDone.clicked[bool].connect( self._handle_place_clicked) self._widget.textSay.keyPressEvent = self._handle_custom_keypress #ros stuff self.pubPick = rospy.Publisher('picker', String, queue_size=10) self.pubPlace = rospy.Publisher('placer', String, queue_size=10) self.pubRecog = rospy.Publisher('recognition/raw_result', String, queue_size=10) self.subRecog = rospy.Subscriber("recognition/raw_result", String, self._recog_callback) self.subLog = rospy.Subscriber("chatbot_gui/log", String, self._log_callback) self.subStatus = rospy.Subscriber("chatbot_gui/status", String, self._status_callback) self.model = QStandardItemModel() self.model.setColumnCount(2) headerNames = [] headerNames.append("Timestamp") headerNames.append("Message") self.model.setHorizontalHeaderLabels(headerNames) self._widget.tableLog.setModel(self.model) self._widget.tableLog.horizontalHeader().setStretchLastSection(True) self._widget.tableLog.setColumnWidth(0, 170) self._message_limit = 20000 self._message_count = 0
def __init__(self, parent): """ @type parent: LaunchMain """ super(LaunchWidget, self).__init__() self._parent = parent self._config = None self._settings = QSettings('ros', 'rqt_launch') self._settings.sync() self._package_update = False self._launchfile_update = False # TODO: should be configurable from gui self._port_roscore = 11311 self._run_id = None self._rospack = rospkg.RosPack() ui_file = os.path.join( self._rospack.get_path('rqt_launch'), 'resource', 'launch_widget.ui' ) loadUi(ui_file, self) # row=0 allows any number of rows to be added. self._datamodel = QStandardItemModel(0, 1) master_uri = rosenv.get_master_uri() rospy.loginfo('LaunchWidget master_uri={}'.format(master_uri)) self._delegate = NodeDelegate(master_uri, self._rospack) self._treeview.setModel(self._datamodel) self._treeview.setItemDelegate(self._delegate) # NodeController used in controller class for launch operation. self._node_controllers = [] self._pushbutton_load_params.clicked.connect(self._parent.load_params) self._pushbutton_start_all.clicked.connect(self._parent.start_all) self._pushbutton_stop_all.clicked.connect(self._parent.stop_all) self._pushbutton_refresh.clicked.connect( self._update_pkgs_contain_launchfiles ) # Bind package selection with .launch file selection. self._combobox_pkg.currentIndexChanged[str].connect( self._refresh_launchfiles ) # Bind a launch file selection with launch GUI generation. self._combobox_launchfile_name.currentIndexChanged[str].connect( self._load_launchfile_slot ) self._update_pkgs_contain_launchfiles()
def __init__(self): ''' Creates a new list model. ''' QStandardItemModel.__init__(self) self.setColumnCount(len(TopicModel.header)) self.setHorizontalHeaderLabels([label for label, _ in TopicModel.header]) topics = ['/rosout', '/rosout_agg', '/diagnostics_agg'] def_list = ['\A' + n.strip().replace('*', '.*') + '\Z' for n in topics] self._re_cap_systopics = re.compile('|'.join(def_list), re.I) self.pyqt_workaround = dict() # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass root_items = TopicGroupItem.create_item_list(rospy.names.SEP, self.invisibleRootItem(), False) self.invisibleRootItem().appendRow(root_items) self._pyqt_workaround_add(rospy.names.SEP, root_items[0])
def _init_variables(self): self.initialised = False #init self._qt_rapp_manager_info = QtRappManagerInfo(self._refresh_rapps) self._update_rapps_signal.connect(self._update_rapp_list) self._rapp_view_model = QStandardItemModel() self._widget.rapp_grid.setModel(self._rapp_view_model) self._widget.rapp_grid.setWrapping(True) self._widget.rapp_grid.setIconSize(QSize(60, 60)) self._widget.rapp_grid.setSpacing(10) self._selected_rapp = None
def __init__(self): ''' Creates a new list model. ''' QStandardItemModel.__init__(self) self.setColumnCount(len(LaunchListModel.header)) self.setHorizontalHeaderLabels([label for label, _width in LaunchListModel.header]) self.pyqt_workaround = dict() # workaround for using with PyQt: store the python object to keep the defined attributes in the TopicItem subclass self.items = [] self.DIR_CACHE = {} self.currentPath = None self.root_paths = [os.path.normpath(p) for p in os.getenv("ROS_PACKAGE_PATH").split(':')] self._setNewList(self._moveUp(None)) self.__packages = {} self._fill_packages_thread = PackagesThread()
def _init_monitor_nodes(self): """ @rtype: Thread """ self._node_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._node_datamodel.invisibleRootItem() self._view_nodes.setModel(self._node_datamodel) node_monitor_thread = threading.Thread(target=self._check_nodes_alive, args=(self.sig_node, self._nodes_monitored, self._stop_event)) self.sig_node.connect(self._update_output_nodes) return node_monitor_thread
def __init__(self, mode, dotgraph , dotcode_factory, dotparser , param_manager, models_desc_file_path, nodename='', parent = None): super(InferenceDialog, self).__init__(parent) if mode not in ['add','edit']: raise Exception('wrong mode for InferenceDialog') self.nodename = nodename self.setWindowTitle("Dialog") self.setGeometry(300,300,450,250) # self._widget = QDialog() ui_file = os.path.join(rospkg.RosPack().get_path('rqt_vino_plugin'), 'resource', 'add_inference_dialog.ui') loadUi(ui_file, self) self.dotgraph = dotgraph self.dotparser = dotparser self.dotcode_factory = dotcode_factory self.available_infers_list = param_manager.parse_inferlist_file(models_desc_file_path) # self.node_name_lineedit.textEdited.connect(self._edit_infer_name) #self.node_infer_name_combobox.activated.connect(self.update_infer_names) self.node_infer_combobox.currentTextChanged.connect(self._select_infer_type) self.connect_from_listmodel = QStandardItemModel()#(self.connect_from_listview) self.connect_to_listmodel = QStandardItemModel()#(self.connect_to_listview) # self.connect_from_listmodel.itemChanged.connect(self._connect_from_changed) #self.connect_to_listview.setModel(self.connect_to_listmodel) self.update_infer_names() self.update_connect_from_list() if mode == 'add': self.buttonBox.accepted.connect(self._create_node_in_graph) elif mode == 'edit': self.buttonBox.accepted.connect(self._edit_node_in_graph)
def __init__(self, tabwidget, parent=None): QDockWidget.__init__(self, "LaunchGraph", parent) graph_ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'GraphDockWidget.ui') loadUi(graph_ui_file, self) self.setObjectName('LaunchGraph') self.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) self._info_icon = QIcon(":/icons/info.png") self._tabwidget = tabwidget self._current_path = None self._root_path = None self._current_deep = 0 self.graphTreeView.setSelectionBehavior(QAbstractItemView.SelectRows) model = QStandardItemModel() self.graphTreeView.setModel(model) self.graphTreeView.setUniformRowHeights(True) self.graphTreeView.header().hide() self.htmlDelegate = HTMLDelegate(palette=self.palette()) self.graphTreeView.setItemDelegateForColumn(0, self.htmlDelegate) self.graphTreeView.activated.connect(self.on_activated) self.graphTreeView.clicked.connect(self.on_clicked) self._created_tree = False self.has_none_packages = True self.has_warnings = False self._refill_tree([], False) self._fill_graph_thread = None
def __init__(self): super(TreeviewWidgetSelectProve, self).__init__() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_prove'), 'resource', #'treeview_non_custom.ui') # Works with pyqt. 'treeview_with_custom.ui') # No good. #loadUi(ui_file, self) loadUi(ui_file, self, {'CustomQTreeview': CustomQTreeview}) self._std_model = QStandardItemModel() self._rootitem = self._std_model.invisibleRootItem() item_r_1 = QStandardItem("r1") self._rootitem.appendRow(item_r_1) print('_rootitem index={}'.format(self._rootitem.index())) self.treeview.setModel(self._std_model) self.selectionModel = self.treeview.selectionModel() self.selectionModel.selectionChanged.connect( self._selection_changed_slot) print('del/sel?\tde/sel index\tde/sel.row\tde/sel.dat\tparent\tinternal id') self.show()
def flags(self, index): # FIXME hardcoded column number flags = QStandardItemModel.flags(self, index) if (index.column() == 3 and index.model().data(index.model().index(index.row(), index.column() - 2, index.parent()), Qt.DisplayRole) == "bool"): flags = flags | Qt.ItemIsUserCheckable | Qt.ItemIsEditable | Qt.ItemIsEnabled return flags
def _init_monitor_nodes(self, nodes_monitored): """ @type params_monitored: str[] @rtype: Thread """ self._node_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._node_datamodel.invisibleRootItem() self._view_nodes.setModel(self._node_datamodel) node_monitor_thread = Thread(target=self._check_nodes_alive, args=(self.sig_node, self._nodes_monitored)) # self._node_monitor_thread = NodeMonitorThread(self, self.sig_node, # nodes_monitored) self.sig_node.connect(self._update_output_nodes) return node_monitor_thread
class TestRqtRosGraph(unittest.TestCase): """ :author: Isaac Saito """ def setUp(self): unittest.TestCase.setUp(self) self._model = QStandardItemModel() node1 = QStandardItem('node1') self._node1_1 = QStandardItem('node1_1') self._node1_1_1 = QStandardItem('node1_1_1') node1_1_2 = QStandardItem('node1_1_2') node1_2 = QStandardItem('node1_2') node1.appendRow(self._node1_1) self._node1_1.appendRow(self._node1_1_1) self._node1_1.appendRow(node1_1_2) node1.appendRow(node1_2) self._model.appendRow(node1) #node_list = [node1, node1_1, self._node1_1_1, node1_1_2, node1_2] #self._model.appendRow(node_list) self._grn_node1_1_1 = '/node1/node1_1/node1_1_1' self._len_lower_grn_node1_1 = 2 def tearDown(self): unittest.TestCase.tearDown(self) del self._model def test_get_upper_grn(self): self.assertEqual(RqtRosGraph.get_upper_grn(self._node1_1_1.index(), ''), self._grn_node1_1_1) def test_get_lower_grn_dfs(self): self.assertEqual(len(RqtRosGraph.get_lower_grn_dfs( self._node1_1.index(), '')), self._len_lower_grn_node1_1) def test_get_full_grn(self): self.assertEqual(RqtRosGraph.get_full_grn(self._node1_1_1.index()), self._grn_node1_1_1)
class TestRqtRosGraph(unittest.TestCase): """ :author: Isaac Saito """ def setUp(self): unittest.TestCase.setUp(self) self._model = QStandardItemModel() node1 = QStandardItem('node1') self._node1_1 = QStandardItem('node1_1') self._node1_1_1 = QStandardItem('node1_1_1') node1_1_2 = QStandardItem('node1_1_2') node1_2 = QStandardItem('node1_2') node1.appendRow(self._node1_1) self._node1_1.appendRow(self._node1_1_1) self._node1_1.appendRow(node1_1_2) node1.appendRow(node1_2) self._model.appendRow(node1) # node_list = [node1, node1_1, self._node1_1_1, node1_1_2, node1_2] # self._model.appendRow(node_list) self._grn_node1_1_1 = '/node1/node1_1/node1_1_1' self._len_lower_grn_node1_1 = 2 def tearDown(self): unittest.TestCase.tearDown(self) del self._model def test_get_upper_grn(self): self.assertEqual( RqtRosGraph.get_upper_grn(self._node1_1_1.index(), ''), self._grn_node1_1_1) def test_get_lower_grn_dfs(self): self.assertEqual( len(RqtRosGraph.get_lower_grn_dfs(self._node1_1.index(), '')), self._len_lower_grn_node1_1) def test_get_full_grn(self): self.assertEqual(RqtRosGraph.get_full_grn(self._node1_1_1.index()), self._grn_node1_1_1)
def _render_messages(self, *messages): """Render simple messages on the canvas""" msg_dot = pydot.Dot() for msg in messages: msg_dot.add_node(pydot.Node(str(uuid.uuid4()), label=str(msg))) self._render_dotgraph(msg_dot) self._render_debug_data(QStandardItemModel(self._scene))
def data(self, index, role): # FIXME hardcoded column number if (index.column() == 3 and index.model().data(index.model().index(index.row(), index.column() - 2, index.parent()), Qt.DisplayRole) == "bool"): if (role == Qt.CheckStateRole): value = index.model().data(index.model().index(index.row(), index.column(), index.parent()), Qt.DisplayRole) if (value == "True"): return Qt.Checked else: return Qt.Unchecked return QStandardItemModel.data(self, index, role)
def _init_monitor_nodes(self, nodes_monitored): """ @type params_monitored: str[] """ self._node_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._node_datamodel.invisibleRootItem() self._view_nodes.setModel(self._node_datamodel) self._node_monitor_thread = NodeMonitorThread(self, self.sig_node, nodes_monitored) self.sig_node.connect(self._monitor_nodes) self._node_monitor_thread.start()
def _init_monitor_parameters(self, params_monitored): """ @type params_monitored: str[] """ self._param_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._param_datamodel.invisibleRootItem() self._view_reconf.setModel(self._param_datamodel) self._param_check_thread = ParamCheckThread(self, self.sig_param, params_monitored) self.sig_param.connect(self._monitor_parameters) self._param_check_thread.start()
def __init__(self, mode, dotgraph, dotcode_factory, dotparser, param_manager, models_desc_file_path, nodename='', parent=None): super(OutputDialog, self).__init__(parent) if mode not in ['add', 'edit']: raise Exception('Wrong mode for Ouput Dialog') self.setWindowTitle("Add a output pipe") self.setGeometry(300, 300, 450, 250) # self._widget = QDialog() ui_file = os.path.join(rospkg.RosPack().get_path('rqt_vino_plugin'), 'resource', 'add_output_dialog.ui') loadUi(ui_file, self) self.dotgraph = dotgraph self.dotparser = dotparser self.dotcode_factory = dotcode_factory self.available_infers_list = param_manager.parse_inferlist_file( models_desc_file_path) self.connect_from_listmodel = QStandardItemModel() self.output_type_combobox.currentTextChanged.connect( self._update_display) self.update_output_types() if mode == 'add': self.buttonBox.accepted.connect(self._create_node_in_graph) elif mode == 'edit': self.nodename = nodename self.buttonBox.accepted.connect(self._edit_node_in_graph)
def setUp(self): unittest.TestCase.setUp(self) self._model = QStandardItemModel() node1 = QStandardItem('node1') self._node1_1 = QStandardItem('node1_1') self._node1_1_1 = QStandardItem('node1_1_1') node1_1_2 = QStandardItem('node1_1_2') node1_2 = QStandardItem('node1_2') node1.appendRow(self._node1_1) self._node1_1.appendRow(self._node1_1_1) self._node1_1.appendRow(node1_1_2) node1.appendRow(node1_2) self._model.appendRow(node1) # node_list = [node1, node1_1, self._node1_1_1, node1_1_2, node1_2] # self._model.appendRow(node_list) self._grn_node1_1_1 = '/node1/node1_1/node1_1_1' self._len_lower_grn_node1_1 = 2
def _on_ctrl_info(self, index): popup = self._popup_widget ctrl = self._controllers[index.row()] popup.ctrl_name.setText(ctrl.name) popup.ctrl_type.setText(ctrl.type) res_model = QStandardItemModel() model_root = QStandardItem('Claimed Resources') res_model.appendRow(model_root) for hw_res in ctrl.claimed_resources: hw_iface_item = QStandardItem(hw_res.hardware_interface) model_root.appendRow(hw_iface_item) for res in hw_res.resources: res_item = QStandardItem(res) hw_iface_item.appendRow(res_item) popup.resource_tree.setModel(res_model) popup.resource_tree.setItemDelegate(FontDelegate(popup.resource_tree)) popup.resource_tree.expandAll() popup.move(QCursor.pos()) popup.show()
def __init__(self, parent): ''' @type parent: LaunchMain ''' super(LaunchWidget, self).__init__() self._parent = parent print 'FROM WIDGET' self._config = None #TODO: should be configurable from gui self._port_roscore = 11311 self._run_id = None self._rospack = rospkg.RosPack() ui_file = os.path.join(self._rospack.get_path('rqt_launch'), 'resource', 'launch_widget.ui') loadUi(ui_file, self) # row=0 allows any number of rows to be added. self._datamodel = QStandardItemModel(0, 1) master_uri = rosenv.get_master_uri() rospy.loginfo('LaunchWidget master_uri={}'.format(master_uri)) self._delegate = NodeDelegate(master_uri, self._rospack) self._treeview.setModel(self._datamodel) self._treeview.setItemDelegate(self._delegate) # NodeController used in controller class for launch operation. self._node_controllers = [] self._pushbutton_start_all.clicked.connect(self._parent.start_all) self._pushbutton_stop_all.clicked.connect(self._parent.stop_all) # Bind package selection with .launch file selection. self._combobox_pkg.currentIndexChanged[str].connect( self._refresh_launchfiles) # Bind a launch file selection with launch GUI generation. self._combobox_launchfile_name.currentIndexChanged[str].connect( self._load_launchfile_slot) self._update_pkgs_contain_launchfiles() # Used for removing previous nodes self._num_nodes_previous = 0
def setUp(self): unittest.TestCase.setUp(self) self._model = QStandardItemModel() node1 = QStandardItem('node1') self._node1_1 = QStandardItem('node1_1') self._node1_1_1 = QStandardItem('node1_1_1') node1_1_2 = QStandardItem('node1_1_2') node1_2 = QStandardItem('node1_2') node1.appendRow(self._node1_1) self._node1_1.appendRow(self._node1_1_1) self._node1_1.appendRow(node1_1_2) node1.appendRow(node1_2) self._model.appendRow(node1) #node_list = [node1, node1_1, self._node1_1_1, node1_1_2, node1_2] #self._model.appendRow(node_list) self._grn_node1_1_1 = '/node1/node1_1/node1_1_1' self._len_lower_grn_node1_1 = 2
def _init_monitor_parameters(self, params_monitored, _col_names_paramtable=None): """ @type params_monitored: str[] """ self._params_monitored = params_monitored self._param_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._param_datamodel.invisibleRootItem() self._view_params.setModel(self._param_datamodel) # Names of header on the QTableView. if not _col_names_paramtable: _col_names_paramtable = ['Param name', 'Found on Parameter Server?'] self._param_datamodel.setHorizontalHeaderLabels(_col_names_paramtable) self.sig_param.connect(self._update_output_parameters) param_check_thread = Thread(target=self._check_params_alive, args=(self.sig_param, self._params_monitored)) return param_check_thread
def to_QItemModel(self): """ Represent the DSDs debug data as QITemModel """ # Return cached result if available if self.__cached_item_model is not None: return self.__cached_item_model # Return empty model when no dsd data was received yet if self.__cached_msg is None: return self.__empty_item_model() # Construct a new item-model model = QStandardItemModel() for i in range(len(self.stack)): elem, _ = self.stack[i] elem_item = QStandardItem() elem_item.setEditable(False) if isinstance(elem, SequenceTreeElement): elem_item.setText('Sequence: ' + ', '.join( str(e) for e in elem.action_elements)) sequence = True else: elem_item.setText(str(elem)) sequence = False self.__append_element_to_item(elem_item, elem.debug_data) model.invisibleRootItem().appendRow(elem_item) # Add a spacer if this is not the last item if elem != self.stack[-1][0]: spacer = QStandardItem() spacer.setEditable(False) model.invisibleRootItem().appendRow(spacer) if sequence: break self.__cached_item_model = model return self.__cached_item_model
class MoveitWidget(QWidget): """#TODO: comment """ # To be connected to PluginContainerWidget sig_sysmsg = None sig_param = Signal(bool, str) # param name emitted sig_node = Signal(bool, str) # param name emitted _SPLITTER_H = 'splitter_horizontal' def __init__(self, parent, plugin_context): """ @type parent: MoveitMain """ self._nodes_monitored = ['/move_group'] self._selected_topics = [('/pointcloud', 'sensor_msgs/PointCloud'), ('/pointcloud2', 'sensor_msgs/PointCloud2'), ('/image', 'sensor_msgs/Image'), ('/camera_info', 'sensor_msgs/CameraInfo')] self._params_monitored = [ '/robot_description', '/robot_description_semantic' ] super(MoveitWidget, self).__init__() self._parent = parent self._plugin_context = plugin_context self._refresh_rate = 5 # With default value self._rospack = rospkg.RosPack() ui_file = os.path.join(self._rospack.get_path('rqt_moveit'), 'resource', 'moveit_top.ui') loadUi(ui_file, self, {'TopicWidget': TopicWidget}) # Custom widget classes don't show in QSplitter when they instantiated # in .ui file and not explicitly added to QSplitter like this. Thus # this is a workaround. self._splitter.addWidget(self._widget_topic) self._spinbox_refreshrate.valueChanged.connect( self._update_refreshrate) # Show default ref rate on QSpinbox self._spinbox_refreshrate.setValue(self._refresh_rate) # Monitor node self._is_checking_nodes = True self._node_qitems = {} self._node_monitor_thread = self._init_monitor_nodes( self._nodes_monitored) self._node_monitor_thread.start() #TODO: connect sys msg for nodes. # topic to show # Delegate GUI functionality to rqt_topic.TopicWidget. self._widget_topic.set_selected_topics(self._selected_topics) self._widget_topic.set_topic_specifier(TopicWidget.SELECT_BY_MSGTYPE) self._widget_topic.start() # To connect signal in a widget to PluginContainerWidget. #TODO: In this way, Signal from only one instance is hooked. # Not a good design at all. self.sig_sysmsg = self._widget_topic.sig_sysmsg # Init monitoring parameters. self._is_checking_params = True self._param_qitems = {} _col_names_paramtable = ['Param name', 'Found on Parameter Server?'] self._param_check_thread = self._init_monitor_parameters( self._params_monitored, _col_names_paramtable) self._param_check_thread.start() def _init_monitor_nodes(self, nodes_monitored): """ @type params_monitored: str[] @rtype: Thread """ self._node_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._node_datamodel.invisibleRootItem() self._view_nodes.setModel(self._node_datamodel) node_monitor_thread = Thread(target=self._check_nodes_alive, args=(self.sig_node, self._nodes_monitored)) # self._node_monitor_thread = NodeMonitorThread(self, self.sig_node, # nodes_monitored) self.sig_node.connect(self._update_output_nodes) return node_monitor_thread def _check_nodes_alive(self, signal, nodes_monitored): """ Working as a callback of Thread class, this method keeps looping to watch if the nodes whose names are passed exist and emits signal per each node. Notice that what MoveitWidget._check_nodes_alive & MoveitWidget._check_params_alive do is very similar, but since both of them are supposed to be passed to Thread class, there might not be a way to generalize these 2. @param signal: Signal(bool, str) @type nodes_monitored: str[] """ while self._is_checking_nodes: rosnode_dynamically_loaded = __import__('rosnode') #from rosnode import rosnode_ping for nodename in nodes_monitored: #TODO: rosnode_ping prints when the node is not found. # Currently I have no idea how to capture that from here. try: #is_node_running = rosnode_ping(nodename, 1) is_node_running = rosnode_dynamically_loaded.rosnode_ping( nodename, 1) except rosnode_dynamically_loaded.ROSNodeIOException as e: #TODO: Needs to be indicated on GUI # (eg. PluginContainerWidget) rospy.logerr(e.message) is_node_running = False signal.emit(is_node_running, nodename) rospy.logdebug('_update_output_nodes') del rosnode_dynamically_loaded time.sleep(self._refresh_rate) def _init_monitor_parameters(self, params_monitored, _col_names_paramtable=None): """ @type params_monitored: str[] """ self._params_monitored = params_monitored self._param_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._param_datamodel.invisibleRootItem() self._view_params.setModel(self._param_datamodel) # Names of header on the QTableView. if not _col_names_paramtable: _col_names_paramtable = [ 'Param name', 'Found on Parameter Server?' ] self._param_datamodel.setHorizontalHeaderLabels(_col_names_paramtable) self.sig_param.connect(self._update_output_parameters) param_check_thread = Thread(target=self._check_params_alive, args=(self.sig_param, self._params_monitored)) return param_check_thread def _update_output_nodes(self, is_node_running, node_name): """ Slot for signals that tell nodes existence. @type is_node_running: bool @type node_name: str """ #TODO: What this method does is exactly the same with # monitor_parameters. Unify them. rospy.logdebug('is_node_running={} par_name={}'.format( is_node_running, node_name)) node_name = str(node_name) node_qitem = None if not node_name in self._node_qitems: node_qitem = QStandardItem(node_name) self._node_qitems[node_name] = node_qitem self._node_datamodel.appendRow(node_qitem) else: # qsitem with the node name already exists. node_qitem = self._node_qitems[str(node_name)] qindex = self._node_datamodel.indexFromItem(node_qitem) _str_node_running = 'Not running' if is_node_running: _str_node_running = 'Running' qitem_node_status = QStandardItem(_str_node_running) self._node_datamodel.setItem(qindex.row(), 1, qitem_node_status) def _check_params_alive(self, signal, params_monitored): """ Working as a callback of Thread class, this method keeps looping to watch if the params whose names are passed exist and emits signal per each node. Notice that what MoveitWidget._check_nodes_alive & MoveitWidget._check_params_alive do is very similar, but since both of them are supposed to be passed to Thread class, there might not be a way to generalize these 2. @type signal: Signal(bool, str) @param_name signal: emitting a name of the parameter that's found. @type params_monitored: str[] """ while self._is_checking_params: # self._is_checking_params only turns to false when the plugin # shuts down. has_param = False for param_name in params_monitored: is_rosmaster_running = RqtRoscommUtil.is_roscore_running() try: if is_rosmaster_running: # Only if rosmaster is running, check if the parameter # exists or not. has_param = rospy.has_param(param_name) except rospy.exceptions.ROSException as e: self.sig_sysmsg.emit( 'Exception upon rospy.has_param {}'.format(e.message)) signal.emit(has_param, param_name) rospy.loginfo('has_param {}, check_param_alive: {}'.format( has_param, param_name)) time.sleep(self._refresh_rate) def _update_output_parameters(self, has_param, param_name): """ Slot @type has_param: bool @type param_name: str """ rospy.logdebug('has_param={} par_name={}'.format( has_param, param_name)) param_name = str(param_name) param_qitem = None if not param_name in self._param_qitems: param_qitem = QStandardItem(param_name) self._param_qitems[param_name] = param_qitem self._param_datamodel.appendRow(param_qitem) else: # qsitem with the param name already exists. param_qitem = self._param_qitems[str(param_name)] qindex = self._param_datamodel.indexFromItem(param_qitem) _str_param_found = 'No' if has_param: _str_param_found = 'Yes' qitem_param_status = QStandardItem(_str_param_found) self._param_datamodel.setItem(qindex.row(), 1, qitem_param_status) self._view_params.resizeColumnsToContents() def _update_refreshrate(self, refresh_rate): """ Slot @type refresh_rate: int """ self._refresh_rate = refresh_rate def save_settings(self, plugin_settings, instance_settings): instance_settings.set_value(self._SPLITTER_H, self._splitter.saveState()) def restore_settings(self, plugin_settings, instance_settings): if instance_settings.contains(self._SPLITTER_H): self._splitter.restoreState( instance_settings.value(self._SPLITTER_H)) else: self._splitter.setSizes([100, 100, 200]) pass def shutdown(self): """ Overridden. Close threads. @raise RuntimeError: """ try: #self._node_monitor_thread.join() # No effect self._is_checking_nodes = False self._node_monitor_thread = None #self._param_check_thread.join() self._is_checking_params = False self._param_check_thread = None except RuntimeError as e: rospy.logerr(e) raise e
class LaunchWidget(QDialog): '''#TODO: comment ''' # To be connected to PluginContainerWidget sig_sysmsg = Signal(str) def __init__(self, parent): ''' @type parent: LaunchMain ''' super(LaunchWidget, self).__init__() self._parent = parent self._config = None #TODO: should be configurable from gui self._port_roscore = 11311 self._run_id = None self._rospack = rospkg.RosPack() ui_file = os.path.join(self._rospack.get_path('rqt_launch'), 'resource', 'launch_widget.ui') loadUi(ui_file, self) # row=0 allows any number of rows to be added. self._datamodel = QStandardItemModel(0, 1) master_uri = rosenv.get_master_uri() rospy.loginfo('LaunchWidget master_uri={}'.format(master_uri)) self._delegate = NodeDelegate(master_uri, self._rospack) self._treeview.setModel(self._datamodel) self._treeview.setItemDelegate(self._delegate) # NodeController used in controller class for launch operation. self._node_controllers = [] self._pushbutton_start_all.clicked.connect(self._parent.start_all) self._pushbutton_stop_all.clicked.connect(self._parent.stop_all) # Bind package selection with .launch file selection. self._combobox_pkg.currentIndexChanged[str].connect( self._refresh_launchfiles) # Bind a launch file selection with launch GUI generation. self._combobox_launchfile_name.currentIndexChanged[str].connect( self._load_launchfile_slot) self._update_pkgs_contain_launchfiles() # Used for removing previous nodes self._num_nodes_previous = 0 def _load_launchfile_slot(self, launchfile_name): # Not yet sure why, but everytime combobox.currentIndexChanged occurs, # this method gets called twice with launchfile_name=='' in 1st call. if launchfile_name == None or launchfile_name == '': return _config = None rospy.logdebug( '_load_launchfile_slot launchfile_name={}'.format(launchfile_name)) try: _config = self._create_launchconfig(launchfile_name, self._port_roscore) #TODO: folder_name_launchfile should be able to specify arbitrarily # _create_launchconfig takes 3rd arg for it. except IndexError as e: msg = 'IndexError={} launchfile={}'.format(e.message, launchfile_name) rospy.logerr(msg) self.sig_sysmsg.emit(msg) return except RLException as e: msg = 'RLException={} launchfile={}'.format( e.message, launchfile_name) rospy.logerr(msg) self.sig_sysmsg.emit(msg) return self._create_widgets_for_launchfile(_config) def _create_launchconfig(self, launchfile_name, port_roscore=11311, folder_name_launchfile='launch'): ''' @rtype: ROSLaunchConfig @raises RLException: raised by roslaunch.config.load_config_default. ''' pkg_name = self._combobox_pkg.currentText() try: launchfile = os.path.join(self._rospack.get_path(pkg_name), folder_name_launchfile, launchfile_name) except IndexError as e: raise RLException('IndexError: {}'.format(e.message)) try: launch_config = roslaunch.config.load_config_default([launchfile], port_roscore) except rospkg.common.ResourceNotFound as e: raise RLException('ResourceNotFound: {}'.format(e.message)) except RLException as e: raise e return launch_config def _create_widgets_for_launchfile(self, config): self._config = config # Delete old nodes' GUIs. self._node_controllers = [] # These lines seem to remove indexWidgets previously set on treeview. # Per suggestion in API doc, we are not using reset(). Instead, # using 2 methods below without any operation in between, which # I suspect might be inproper. # http://qt-project.org/doc/qt-4.8/qabstractitemmodel.html#reset self._datamodel.beginResetModel() self._datamodel.endResetModel() # Need to store the num of nodes outside of the loop -- this will # be used for removing excessive previous node rows. order_xmlelement = 0 # Loop per xml element for order_xmlelement, node in enumerate(self._config.nodes): proxy = NodeProxy(self._run_id, self._config.master.uri, node) # TODO: consider using QIcon.fromTheme() status_label = StatusIndicator() qindex_nodewidget = self._datamodel.index(order_xmlelement, 0, QModelIndex()) node_widget = self._delegate.create_node_widget( qindex_nodewidget, proxy.config, status_label) #TODO: Ideally find a way so that we don't need this block. #BEGIN If these lines are missing, widget won't be shown either. std_item = QStandardItem( #node_widget.get_node_name() ) self._datamodel.setItem(order_xmlelement, 0, std_item) #END If these lines are missing, widget won't be shown either. self._treeview.setIndexWidget(qindex_nodewidget, node_widget) node_controller = NodeController(proxy, node_widget) self._node_controllers.append(node_controller) node_widget.connect_start_stop_button( \ node_controller.start_stop_slot) rospy.logdebug( 'loop #%d proxy.config.namespace=%s ' + 'proxy.config.name=%s', order_xmlelement, proxy.config.namespace, proxy.config.name) self._num_nodes_previous = order_xmlelement self._parent.set_node_controllers(self._node_controllers) def _update_pkgs_contain_launchfiles(self): ''' Inspired by rqt_msg.MessageWidget._update_pkgs_contain_launchfiles ''' packages = sorted([ pkg_tuple[0] for pkg_tuple in RqtRoscommUtil.iterate_packages('launch') ]) self._package_list = packages rospy.logdebug('pkgs={}'.format(self._package_list)) self._combobox_pkg.clear() self._combobox_pkg.addItems(self._package_list) self._combobox_pkg.setCurrentIndex(0) def _refresh_launchfiles(self, package=None): ''' Inspired by rqt_msg.MessageWidget._refresh_msgs ''' if package is None or len(package) == 0: return self._launchfile_instances = [] # Launch[] #TODO: RqtRoscommUtil.list_files's 2nd arg 'subdir' should NOT be # hardcoded later. _launch_instance_list = RqtRoscommUtil.list_files(package, 'launch') rospy.logdebug('_refresh_launches package={} instance_list={}'.format( package, _launch_instance_list)) self._launchfile_instances = [ x.split('/')[1] for x in _launch_instance_list ] self._combobox_launchfile_name.clear() self._combobox_launchfile_name.addItems(self._launchfile_instances) def save_settings(self, plugin_settings, instance_settings): # instance_settings.set_value('splitter', self._splitter.saveState()) pass def restore_settings(self, plugin_settings, instance_settings): # if instance_settings.contains('splitter'): # self._splitter.restoreState(instance_settings.value('splitter')) # else: # self._splitter.setSizes([100, 100, 200]) pass
def __init__(self, context): super(Conman, self).__init__(context) self._dotcode_sub = None # Give QObjects reasonable names self.setObjectName('Conman') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which is a sibling of this file # in this example the .ui and .py file are in the same folder ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'rqt_conman.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('ConmanPluginUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) palette = QPalette () palette.setColor(QPalette.Background, Qt.white) self._widget.setPalette(palette) #self._widget.subscribe_button.setCheckable(True) self._widget.refresh_button.clicked[bool].connect(self._handle_refresh_clicked) self._widget.commit_button.clicked[bool].connect(self._handle_commit_clicked) #self._widget.xdot_widget.connect( #self._widget.xdot_widget, SIGNAL('_update_graph'), self._widget.xdot_widget.set_dotcode) self.update_graph_sig.connect(self._update_graph) self.blocks = { } self.groups = { } self._ns = "" self._actions_connected = False self.enable_widgets(False) self.new_dotcode_data = '' self.update_timer = QTimer(self) self.update_timer.setInterval(50) self.update_timer.timeout.connect(self._update_widgets) #self.update_timer.start() self._get_blocks = None self._set_blocks = None self._blocks_model = QStandardItemModel(0,4) self._blocks_model.setHeaderData(0, Qt.Horizontal, "") self._blocks_model.setHeaderData(1, Qt.Horizontal, "Action") self._blocks_model.setHeaderData(2, Qt.Horizontal, "State") self._blocks_model.setHeaderData(3, Qt.Horizontal, "Block") self._widget.blocks_table.setModel(self._blocks_model) self._blocks_delegate = BlocksDelegate(self) self._widget.blocks_table.setItemDelegate(self._blocks_delegate) self._blocks_model.itemChanged.connect(self.block_changed) self._groups_model = QStandardItemModel(0,4) self._groups_model.setHeaderData(0, Qt.Horizontal, "") self._groups_model.setHeaderData(1, Qt.Horizontal, "") self._groups_model.setHeaderData(2, Qt.Horizontal, "") self._groups_model.setHeaderData(3, Qt.Horizontal, "Group") self._widget.groups_table.setModel(self._groups_model) self._groups_delegate = GroupsDelegate(self) self._widget.groups_table.setItemDelegate(self._groups_delegate)
class RqtSrVisualServoing(Plugin): def __init__(self, context): super(RqtSrVisualServoing, self).__init__(context) # Give QObjects reasonable names self.setObjectName('RqtSrVisualServoing') # # Process standalone plugin command-line arguments # from argparse import ArgumentParser # parser = ArgumentParser() # # Add argument(s) to the parser. # parser.add_argument("-q", "--quiet", action="store_true", # dest="quiet", # help="Put plugin in silent mode") # args, unknowns = parser.parse_known_args(context.argv()) # if not args.quiet: # print 'arguments: ', args # print 'unknowns: ', unknowns # Create QWidget self.ui = QWidget() # Get path to UI file which is in our packages resource directory rp = rospkg.RosPack() self.ui_file = os.path.join(rp.get_path(PKG), 'resource', 'gui.ui') # Extend the widget with all attributes and children from UI file loadUi(self.ui_file, self.ui) # Give QObjects reasonable names self.ui.setObjectName('RqtSrVisualServoingUi') # Show ui.windowTitle on left-top of each plugin (when it's set in ui). # This is useful when you open multiple plugins at once. Also if you # open multiple instances of your plugin at once, these lines add # number to make it easy to tell from pane to pane. if context.serial_number() > 1: self.ui.setWindowTitle(self.ui.windowTitle() + (' (%d)' % context.serial_number())) # Wire up the buttons self.ui.startBtn.clicked.connect( self.start_clicked ) self.ui.stopBtn.clicked.connect( self.stop_clicked ) # Annoyingly setting the icon theme in designer only works in designer, # we have to set it again here for it to work at run time self.ui.startBtn.setIcon(QIcon.fromTheme('media-playback-start')) self.ui.stopBtn.setIcon(QIcon.fromTheme('media-playback-stop')) # Add widget to the user interface context.add_widget(self.ui) # Setup a model for the feedback and link to the view. self.feedback_model = QStandardItemModel(0,2) self.feedback_model.setHorizontalHeaderLabels(['Name','Value']) self.ui.feedbackView.setModel(self.feedback_model) self.ui.connect( self.ui, SIGNAL('feedback(QString)'), self.update_feedback ) # ROS setup self.last_feedback = None self.client = actionlib.SimpleActionClient('visual_servo', VisualServoingAction) msg = "" if self.client.wait_for_server(rospy.Duration(2.0)): msg = "Found action server, servoing appears to be running" rospy.loginfo(msg) else: msg = "Can't find action server, servoing not running" rospy.logerr(msg) self.ui.statusValue.setText(msg) def shutdown_plugin(self): # TODO unregister all publishers here pass def save_settings(self, plugin_settings, instance_settings): # TODO save intrinsic configuration, usually using: # instance_settings.set_value(k, v) pass def restore_settings(self, plugin_settings, instance_settings): # TODO restore intrinsic configuration, usually using: # v = instance_settings.value(k) pass #def trigger_configuration(self): # Comment in to signal that the plugin has a way to configure it # Usually used to open a configuration dialog def start_clicked(self): goal = VisualServoingActionGoal() self.client.send_goal(goal, feedback_cb = self._feedback_cb) self.ui.statusValue.setText("Starting") def stop_clicked(self): self.client.cancel_all_goals() self.ui.statusValue.setText("Stopped") self.feedback_model.clear() def _feedback_cb(self, feedback): # We can't update the UI in this thread so stash the data and emit a # signal that can be traped by the main thread and update the ui. self.last_feedback = feedback self.ui.emit( SIGNAL('feedback(QString)'), "" ) def update_feedback(self, data): """Listen for feedback signals and update the interface.""" fb = self.last_feedback self.ui.statusValue.setText(str(self.client.get_goal_status_text())) # Update the feedback model, which triggers the view to update m = self.feedback_model m.setHorizontalHeaderLabels(['Name','Value']) m.setItem(0,0,QStandardItem('distance')) m.setItem(0,1,QStandardItem(str(fb.distance))) m.setItem(1,0,QStandardItem('object_pose.position.x')) m.setItem(1,1,QStandardItem(str(fb.object_pose.position.x))) m.setItem(2,0,QStandardItem('object_pose.position.y')) m.setItem(2,1,QStandardItem(str(fb.object_pose.position.y))) m.setItem(3,0,QStandardItem('object_pose.position.z')) m.setItem(3,1,QStandardItem(str(fb.object_pose.position.z))) m.setItem(4,0,QStandardItem('object_pose.orientation.x')) m.setItem(4,1,QStandardItem(str(fb.object_pose.orientation.x))) m.setItem(5,0,QStandardItem('object_pose.orientation.y')) m.setItem(5,1,QStandardItem(str(fb.object_pose.orientation.y))) m.setItem(6,0,QStandardItem('object_pose.orientation.z')) m.setItem(6,1,QStandardItem(str(fb.object_pose.orientation.z))) m.setItem(7,0,QStandardItem('object_pose.orientation.w')) m.setItem(7,1,QStandardItem(str(fb.object_pose.orientation.w))) m.setItem(8,0,QStandardItem('grasp_pose.position.x')) m.setItem(8,1,QStandardItem(str(fb.grasp_pose.position.x))) m.setItem(9,0,QStandardItem('grasp_pose.position.y')) m.setItem(9,1,QStandardItem(str(fb.grasp_pose.position.y))) m.setItem(10,0,QStandardItem('grasp_pose.position.z')) m.setItem(10,1,QStandardItem(str(fb.grasp_pose.position.z))) m.setItem(11,0,QStandardItem('grasp_pose.orientation.x')) m.setItem(11,1,QStandardItem(str(fb.grasp_pose.orientation.x))) m.setItem(12,0,QStandardItem('grasp_pose.orientation.y')) m.setItem(12,1,QStandardItem(str(fb.grasp_pose.orientation.y))) m.setItem(13,0,QStandardItem('grasp_pose.orientation.z')) m.setItem(13,1,QStandardItem(str(fb.grasp_pose.orientation.z))) m.setItem(14,0,QStandardItem('grasp_pose.orientation.w')) m.setItem(14,1,QStandardItem(str(fb.grasp_pose.orientation.w))) self.ui.feedbackView.resizeColumnsToContents()
class QtRappManager(Plugin): _update_rapps_signal = Signal() def __init__(self, context): self._context = context super(QtRappManager, self).__init__(context) self._init_ui(context) self._init_events() self._init_variables() self.spin() def _init_ui(self, context): self._widget = QWidget() self.setObjectName('QtRappManger') rospack = rospkg.RosPack() ui_file = os.path.join(rospack.get_path('rocon_qt_app_manager'), 'ui', 'qt_rapp_manager.ui') self._widget.setObjectName('QtRappManger') loadUi(ui_file, self._widget, {}) if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) # Set view mode self._widget.rapp_grid.setViewMode(QListView.IconMode) #self._widget.rapp_grid.setViewMode(QListView.ListMode) def _init_events(self): #combo box change event self._widget.namespace_cbox.currentIndexChanged.connect( self._change_namespace) # Rapp single click event self._widget.rapp_grid.clicked.connect(self._rapp_single_click) # Rapp double click event self._widget.rapp_grid.doubleClicked.connect(self._rapp_double_click) def _init_variables(self): self.initialised = False #init self._qt_rapp_manager_info = QtRappManagerInfo(self._refresh_rapps) self._update_rapps_signal.connect(self._update_rapp_list) self._rapp_view_model = QStandardItemModel() self._widget.rapp_grid.setModel(self._rapp_view_model) self._widget.rapp_grid.setWrapping(True) self._widget.rapp_grid.setIconSize(QSize(60, 60)) self._widget.rapp_grid.setSpacing(10) self._selected_rapp = None def spin(self): self._get_appmanager_namespaces() def _cleanup_rapps(self): self._rapp_view_model.clear() pass def _get_appmanager_namespaces(self): namespaces = self._qt_rapp_manager_info._get_namespaces() for namespace in namespaces: ns = namespace[:namespace.find('list_rapps')] self._widget.namespace_cbox.addItem(ns) def _exit(self): pass ################################################################### # Events ################################################################### def _change_namespace(self, event): self._qt_rapp_manager_info.select_rapp_manager( self._widget.namespace_cbox.currentText()) def _refresh_rapps(self): """ Updates from qt_app_manager_info. """ self._update_rapps_signal.emit() def _update_rapp_list(self): """ Rapp manager namespace event """ self._cleanup_rapps() available_rapps = self._qt_rapp_manager_info.get_available_rapps() running_rapps = self._qt_rapp_manager_info.get_running_rapps() rapp_items = [] for r, v in available_rapps.items(): if r in running_rapps.keys(): item = QRappItem(v, running=True) else: item = QRappItem(v, running=False) self._rapp_view_model.appendRow(item) def _rapp_single_click(self, index): qrapp = self._rapp_view_model.item(index.row()) rapp = qrapp.getRapp() self._create_rapp_dialog(rapp) def _create_rapp_dialog(self, rapp): is_running = self._qt_rapp_manager_info.is_running_rapp(rapp) self._selected_rapp = rapp self._dialog = QtRappDialog(self._widget, rapp, self._qt_rapp_manager_info.start_rapp, self._qt_rapp_manager_info.stop_rapp, is_running) self._dialog.show() def _rapp_double_click(self, item): running_rapps = self._qt_rapp_manager_info.get_running_rapps() if len(running_rapps) > 0: names = [r['display_name'] for r in running_rapps.values()] show_message(self._widget, "Error", "Rapp %s are already running" % names) else: self._start_rapp() def _start_rapp(self): result = self._qt_rapp_manager_info.start_rapp( self._selected_rapp['name'], [], self._selected_rapp['public_parameters']) show_message(self._widget, str(result.started), result.message) self._selected_rapp = None return result def _stop_rapp(self): result = self._qt_rapp_manager_info.stop_rapp() show_message(self._widget, str(result.stopped), result.message) self._selected_rapp = None return result ######################################## # Legacy ######################################## def _select_rapp_tree_item(self, item): if not item in self.rapps.keys(): print "HAS NO KEY" else: self.current_rapp = self.rapps[item] self._widget.rapp_info_text.clear() rapp_info = self.qt_rapp_manager_info._get_rapp_info(self.current_rapp) self._widget.rapp_info_text.appendHtml(rapp_info) self._update_rapp_parameter_layout(self.current_rapp) self._update_implementation_tree(self.current_rapp) def _update_rapp_parameter_layout(self, rapp): parameters_layout = self._widget.rapp_parameter_layout clear_layout(parameters_layout) for param in rapp['public_parameters']: one_param_layout = create_label_textedit_pair( param.key, param.value) parameters_layout.addLayout(one_param_layout) 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 _select_implementation_tree_item(self, item): if not item in self.impls.keys(): print "HAS NO KEY" else: self.selected_impl = self.impls[item] def _get_public_parameters(self): public_parameters = {} parameters_layout = self._widget.rapp_parameter_layout for i in reversed(range(parameters_layout.count())): item = parameters_layout.itemAt(i) key_label = item.itemAt(0).widget() value_textbox = item.itemAt(1).widget() public_parameters[key_label.text()] = str( value_textbox.toPlainText()) return public_parameters
def __init__(self, context): super(RqtSrVisualServoing, self).__init__(context) # Give QObjects reasonable names self.setObjectName('RqtSrVisualServoing') # # Process standalone plugin command-line arguments # from argparse import ArgumentParser # parser = ArgumentParser() # # Add argument(s) to the parser. # parser.add_argument("-q", "--quiet", action="store_true", # dest="quiet", # help="Put plugin in silent mode") # args, unknowns = parser.parse_known_args(context.argv()) # if not args.quiet: # print 'arguments: ', args # print 'unknowns: ', unknowns # Create QWidget self.ui = QWidget() # Get path to UI file which is in our packages resource directory rp = rospkg.RosPack() self.ui_file = os.path.join(rp.get_path(PKG), 'resource', 'gui.ui') # Extend the widget with all attributes and children from UI file loadUi(self.ui_file, self.ui) # Give QObjects reasonable names self.ui.setObjectName('RqtSrVisualServoingUi') # Show ui.windowTitle on left-top of each plugin (when it's set in ui). # This is useful when you open multiple plugins at once. Also if you # open multiple instances of your plugin at once, these lines add # number to make it easy to tell from pane to pane. if context.serial_number() > 1: self.ui.setWindowTitle(self.ui.windowTitle() + (' (%d)' % context.serial_number())) # Wire up the buttons self.ui.startBtn.clicked.connect( self.start_clicked ) self.ui.stopBtn.clicked.connect( self.stop_clicked ) # Annoyingly setting the icon theme in designer only works in designer, # we have to set it again here for it to work at run time self.ui.startBtn.setIcon(QIcon.fromTheme('media-playback-start')) self.ui.stopBtn.setIcon(QIcon.fromTheme('media-playback-stop')) # Add widget to the user interface context.add_widget(self.ui) # Setup a model for the feedback and link to the view. self.feedback_model = QStandardItemModel(0,2) self.feedback_model.setHorizontalHeaderLabels(['Name','Value']) self.ui.feedbackView.setModel(self.feedback_model) self.ui.connect( self.ui, SIGNAL('feedback(QString)'), self.update_feedback ) # ROS setup self.last_feedback = None self.client = actionlib.SimpleActionClient('visual_servo', VisualServoingAction) msg = "" if self.client.wait_for_server(rospy.Duration(2.0)): msg = "Found action server, servoing appears to be running" rospy.loginfo(msg) else: msg = "Can't find action server, servoing not running" rospy.logerr(msg) self.ui.statusValue.setText(msg)
class Conman(Plugin): update_graph_sig = Signal(str) def __init__(self, context): super(Conman, self).__init__(context) self._dotcode_sub = None # Give QObjects reasonable names self.setObjectName('Conman') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which is a sibling of this file # in this example the .ui and .py file are in the same folder ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'rqt_conman.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('ConmanPluginUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) palette = QPalette () palette.setColor(QPalette.Background, Qt.white) self._widget.setPalette(palette) #self._widget.subscribe_button.setCheckable(True) self._widget.refresh_button.clicked[bool].connect(self._handle_refresh_clicked) self._widget.commit_button.clicked[bool].connect(self._handle_commit_clicked) #self._widget.xdot_widget.connect( #self._widget.xdot_widget, SIGNAL('_update_graph'), self._widget.xdot_widget.set_dotcode) self.update_graph_sig.connect(self._update_graph) self.blocks = { } self.groups = { } self._ns = "" self._actions_connected = False self.enable_widgets(False) self.new_dotcode_data = '' self.update_timer = QTimer(self) self.update_timer.setInterval(50) self.update_timer.timeout.connect(self._update_widgets) #self.update_timer.start() self._get_blocks = None self._set_blocks = None self._blocks_model = QStandardItemModel(0,4) self._blocks_model.setHeaderData(0, Qt.Horizontal, "") self._blocks_model.setHeaderData(1, Qt.Horizontal, "Action") self._blocks_model.setHeaderData(2, Qt.Horizontal, "State") self._blocks_model.setHeaderData(3, Qt.Horizontal, "Block") self._widget.blocks_table.setModel(self._blocks_model) self._blocks_delegate = BlocksDelegate(self) self._widget.blocks_table.setItemDelegate(self._blocks_delegate) self._blocks_model.itemChanged.connect(self.block_changed) self._groups_model = QStandardItemModel(0,4) self._groups_model.setHeaderData(0, Qt.Horizontal, "") self._groups_model.setHeaderData(1, Qt.Horizontal, "") self._groups_model.setHeaderData(2, Qt.Horizontal, "") self._groups_model.setHeaderData(3, Qt.Horizontal, "Group") self._widget.groups_table.setModel(self._groups_model) self._groups_delegate = GroupsDelegate(self) self._widget.groups_table.setItemDelegate(self._groups_delegate) def block_changed(self, item): row = item.row() name = self._blocks_model.item(row,3).text() block = self.blocks[name] checked = item.checkState() == Qt.Checked def shutdown_plugin(self): # TODO unregister all publishers here pass def save_settings(self, plugin_settings, instance_settings): # TODO save intrinsic configuration, usually using: # instance_settings.set_value(k, v) pass def restore_settings(self, plugin_settings, instance_settings): # TODO restore intrinsic configuration, usually using: # v = instance_settings.value(k) pass #def trigger_configuration(self): # Comment in to signal that the plugin has a way to configure # This will enable a setting button (gear icon) in each dock widget title bar # Usually used to open a modal configuration dialog def _get_result_cb(self, status, res): rospy.loginfo("got result!") self._blocks_model.setRowCount(0) self._blocks_model.setRowCount(len(res.blocks)) for (i,block) in zip(range(len(res.blocks)),res.blocks): # Store in dict self.blocks[block.name] = block cb = QStandardItem(True) cb.setCheckable(True) cb.setCheckState(Qt.Checked if block.state.value == conman_msgs.msg.TaskState.RUNNING else Qt.Unchecked) cb.setTextAlignment(Qt.AlignHCenter) cb.setTristate(True) action = QStandardItem(True) action.setText("") state = QStandardItem(True) state.setText(state_map[block.state.value]) name = QStandardItem(True) name.setText(str(block.name)) self._blocks_model.setItem(i,0,cb) self._blocks_model.setItem(i,1,action) self._blocks_model.setItem(i,2,state) self._blocks_model.setItem(i,3,name) for (i,group) in zip(range(len(res.groups)),res.groups): self.groups[group.name] = group cb = QStandardItem(True) cb.setCheckable(True) cb.setCheckState(Qt.Checked) cb.setTextAlignment(Qt.AlignHCenter) cb.setEnabled(False) name = QStandardItem(True) name.setText(str(group.name)) self._groups_model.setItem(i,0,cb) self._groups_model.setItem(i,3,name) self._update_groups() self._update_blocks() self._widget.blocks_table.resizeColumnsToContents() self._widget.blocks_table.horizontalHeader().setStretchLastSection(True) self._widget.groups_table.resizeColumnsToContents() self._widget.groups_table.horizontalHeader().setStretchLastSection(True) def _update_blocks(self): for (name, block) in self.blocks.items(): items = self._blocks_model.findItems(name, column=3) if len(items) > 0: item = items[0] else: continue row = item.row() checked = self._blocks_model.item(row,0).checkState() == Qt.Checked if checked and block.state.value != conman_msgs.msg.TaskState.RUNNING: self._blocks_model.item(row,1).setText("ENABLE") elif not checked and block.state.value == conman_msgs.msg.TaskState.RUNNING: self._blocks_model.item(row,1).setText("DISABLE") else: self._blocks_model.item(row,1).setText("") self._update_groups() def _enable_group(self, index, enable): name = self._groups_model.item(index, 3).text() group = self.groups[name] for member in group.members: items = self._blocks_model.findItems(member, column=3) if len(items) > 0: item = items[0] else: continue row = item.row() self._blocks_model.item(row,0).setCheckState(Qt.Checked if enable else Qt.Unchecked) self._update_blocks() def _update_groups(self): for (name, group) in self.groups.items(): group_items = self._groups_model.findItems(name, column=3) if len(group_items) > 0: group_item = group_items[0] else: continue group_row = group_item.row() members_checked = [] for member in group.members: items = self._blocks_model.findItems(member, column=3) if len(items) > 0: item = items[0] else: continue row = item.row() members_checked.append(self._blocks_model.item(row,0).checkState() == Qt.Checked) if all(members_checked): check = Qt.Checked else: check = Qt.Unchecked self._groups_model.item(group_row,0).setCheckState(check) def _query_blocks(self): if self._get_blocks and self._actions_connected: if self._get_blocks.simple_state == actionlib.SimpleGoalState.DONE: rospy.loginfo("Getting blocks...") goal = conman_msgs.msg.GetBlocksGoal() goal.publish_flow_graph = self._widget.generate_graph_checkbox.isChecked() self._get_blocks.send_goal(goal, done_cb=self._get_result_cb) def enable_widgets(self, enable): #self._widget.generate_graph_checkbox.setEnabled(enable) self._widget.force_enable_checkbox.setEnabled(enable) #self._widget.disable_unused_button.setEnabled(enable) self._widget.xdot_widget.setEnabled(enable) self._widget.blocks_table.setEnabled(enable) self._widget.groups_table.setEnabled(enable) self._widget.regenerate_graph_button.setEnabled(enable) def _handle_refresh_clicked(self, checked): ns = self._widget.namespace_input.text() if len(ns) > 0: if self._ns != ns: self._actions_connected = False self._ns = ns self.enable_widgets(False) self._dotcode_sub = rospy.Subscriber( ns+'/dotcode', std_msgs.msg.String, self._dotcode_msg_cb) self._get_blocks = actionlib.SimpleActionClient( ns+'/get_blocks_action', conman_msgs.msg.GetBlocksAction) self._set_blocks = actionlib.SimpleActionClient( ns+'/set_blocks_action', conman_msgs.msg.SetBlocksAction) rospy.loginfo("Creating action clients on namespace '%s'..." % ns) if not self._get_blocks.wait_for_server(rospy.Duration(2)): rospy.loginfo("Timed out waiting for %s." % self._get_blocks.action_client.ns) return if not self._set_blocks.wait_for_server(rospy.Duration(2)): rospy.loginfo("Timed out waiting for %s." % self._set_blocks.action_client.ns) return rospy.loginfo("Action clients created.") self._actions_connected = True self.enable_widgets(True) self._query_blocks() def _handle_commit_clicked(self, checked): if self._set_blocks and self._actions_connected: if self._get_blocks.simple_state == actionlib.SimpleGoalState.DONE: rospy.loginfo("Setting blocks...") goal = conman_msgs.msg.SetBlocksGoal() goal.diff = True goal.force = True for i in range(self._blocks_model.rowCount()): name = self._blocks_model.item(i,3).text() action = self._blocks_model.item(i,1).text() if action == 'DISABLE': goal.disable.append(name) elif action == 'ENABLE': goal.enable.append(name) self._set_blocks.send_goal(goal, done_cb=self._get_set_result_cb) def _get_set_result_cb(self, status, res): self._query_blocks() @Slot(str) def _update_graph(self,dotcode): self._widget.xdot_widget.set_dotcode(dotcode, center=False) def _dotcode_msg_cb(self, msg): #self.new_dotcode_data = msg.data self.update_graph_sig.emit(msg.data) def _update_widgets(self): self._update_groups() self._update_blocks()
class MoveitWidget(QWidget): """#TODO: comment """ # To be connected to PluginContainerWidget sig_sysmsg = None sig_param = Signal(bool, str) # param name emitted sig_node = Signal(bool, str) # param name emitted def __init__(self, parent, plugin_context): """ @type parent: MoveitMain """ self._nodes_monitored = ['/move_group'] self._selected_topics = [('/pointcloud', 'sensor_msgs/PointCloud'), ('/pointcloud2', 'sensor_msgs/PointCloud2'), ('/image', 'sensor_msgs/Image'), ('/camera_info', 'sensor_msgs/CameraInfo')] _params_monitored = ['/robot_description', '/robot_description_semantic'] super(MoveitWidget, self).__init__() self._parent = parent self._plugin_context = plugin_context self._rospack = rospkg.RosPack() ui_file = os.path.join(self._rospack.get_path('rqt_moveit'), 'resource', 'moveit_top.ui') loadUi(ui_file, self, {'TopicWidget': TopicWidget}) # Monitor node self._node_qitems = {} self._init_monitor_nodes(self._nodes_monitored) #TODO: connect sys msg for nodes. # topic to show # Delegate GUI functionality to rqt_topic.TopicWidget. self._widget_topic.set_selected_topics(self._selected_topics) self._widget_topic.set_topic_specifier(TopicWidget.SELECT_BY_MSGTYPE) self._widget_topic.start() # To connect signal in a widget to PluginContainerWidget. #TODO: In this way, Signal from only one instance is hooked. # Not a good design at all. self.sig_sysmsg = self._widget_topic.sig_sysmsg # Init monitoring parameters. self._param_qitems = {} self._init_monitor_parameters(_params_monitored) def _init_monitor_nodes(self, nodes_monitored): """ @type params_monitored: str[] """ self._node_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._node_datamodel.invisibleRootItem() self._view_nodes.setModel(self._node_datamodel) self._node_monitor_thread = NodeMonitorThread(self, self.sig_node, nodes_monitored) self.sig_node.connect(self._monitor_nodes) self._node_monitor_thread.start() def _init_monitor_parameters(self, params_monitored): """ @type params_monitored: str[] """ self._param_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._param_datamodel.invisibleRootItem() self._view_reconf.setModel(self._param_datamodel) self._param_check_thread = ParamCheckThread(self, self.sig_param, params_monitored) self.sig_param.connect(self._monitor_parameters) self._param_check_thread.start() def _monitor_nodes(self, is_node_running, node_name): """ Slot @type is_node_running: bool @type node_name: str """ #TODO: What this method does is exactly the same with # monitor_parameters. Unify them. rospy.logdebug('is_node_running={} par_name={}'.format(is_node_running, node_name)) node_name = str(node_name) node_qitem = None if not node_name in self._node_qitems: node_qitem = QStandardItem(node_name) self._node_qitems[node_name] = node_qitem self._node_datamodel.appendRow(node_qitem) else: # qsitem with the node name already exists. node_qitem = self._node_qitems[str(node_name)] qindex = self._node_datamodel.indexFromItem(node_qitem) _str_node_running = 'Not running' if is_node_running: _str_node_running = 'Running' qitem_node_status = QStandardItem(_str_node_running) self._node_datamodel.setItem(qindex.row(), 1, qitem_node_status) def _monitor_parameters(self, has_param, param_name): """ Slot @type has_param: bool @type param_name: str """ rospy.logdebug('has_param={} par_name={}'.format(has_param, param_name)) param_name = str(param_name) param_qitem = None if not param_name in self._param_qitems: param_qitem = QStandardItem(param_name) self._param_qitems[param_name] = param_qitem self._param_datamodel.appendRow(param_qitem) else: # qsitem with the param name already exists. param_qitem = self._param_qitems[str(param_name)] qindex = self._param_datamodel.indexFromItem(param_qitem) _str_param_found = 'Not found on Parameter Server' if has_param: _str_param_found = 'Found on Parameter Server' qitem_param_status = QStandardItem(_str_param_found) self._param_datamodel.setItem(qindex.row(), 1, qitem_param_status) #.insertColumn([qitem_param_status]) def save_settings(self, plugin_settings, instance_settings): # instance_settings.set_value('splitter', self._splitter.saveState()) pass def restore_settings(self, plugin_settings, instance_settings): # if instance_settings.contains('splitter'): # self._splitter.restoreState(instance_settings.value('splitter')) # else: # self._splitter.setSizes([100, 100, 200]) pass def shutdown(self): # TODO: impl pass
def __init__(self): """ Initializes the ModelLogger. """ self.__log_model = QStandardItemModel(0, 4, None) self.__log_model.setHorizontalHeaderLabels(["type", "date", "location", "message"])
class QtRappManager(Plugin): _update_rapps_signal = Signal() def __init__(self, context): self._context = context super(QtRappManager, self).__init__(context) self._init_ui(context) self._init_events() self._init_variables() self.spin() def _init_ui(self, context): self._widget = QWidget() self.setObjectName('QtRappManger') rospack = rospkg.RosPack() ui_file = os.path.join(rospack.get_path('rocon_qt_app_manager'), 'ui', 'qt_rapp_manager.ui') self._widget.setObjectName('QtRappManger') loadUi(ui_file, self._widget, {}) if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) # Set view mode self._widget.rapp_grid.setViewMode(QListView.IconMode) # self._widget.rapp_grid.setViewMode(QListView.ListMode) def _init_events(self): # combo box change event self._widget.namespace_cbox.currentIndexChanged.connect( self._change_namespace) # Rapp single click event self._widget.rapp_grid.clicked.connect(self._rapp_single_click) # Rapp double click event self._widget.rapp_grid.doubleClicked.connect(self._rapp_double_click) def _init_variables(self): self.initialised = False # init self._qt_rapp_manager_info = QtRappManagerInfo(self._refresh_rapps) self._update_rapps_signal.connect(self._update_rapp_list) self._rapp_view_model = QStandardItemModel() self._widget.rapp_grid.setModel(self._rapp_view_model) self._widget.rapp_grid.setWrapping(True) self._widget.rapp_grid.setIconSize(QSize(60, 60)) self._widget.rapp_grid.setSpacing(10) self._selected_rapp = None def spin(self): self._get_appmanager_namespaces() def _cleanup_rapps(self): self._rapp_view_model.clear() def _get_appmanager_namespaces(self): namespaces = self._qt_rapp_manager_info._get_namespaces() for namespace in namespaces: ns = namespace[:namespace.find('list_rapps')] self._widget.namespace_cbox.addItem(ns) def _exit(self): pass ################################################################### # Events ################################################################### def _change_namespace(self, event): self._qt_rapp_manager_info.select_rapp_manager( self._widget.namespace_cbox.currentText()) def _refresh_rapps(self): """ Updates from qt_app_manager_info. """ self._update_rapps_signal.emit() def _update_rapp_list(self): """ Rapp manager namespace event """ self._cleanup_rapps() available_rapps = self._qt_rapp_manager_info.get_available_rapps() running_rapps = self._qt_rapp_manager_info.get_running_rapps() for r, v in available_rapps.items(): if r in running_rapps.keys(): item = QRappItem(v, running=True) else: item = QRappItem(v, running=False) self._rapp_view_model.appendRow(item) def _rapp_single_click(self, index): qrapp = self._rapp_view_model.item(index.row()) rapp = qrapp.getRapp() self._create_rapp_dialog(rapp) def _create_rapp_dialog(self, rapp): is_running = self._qt_rapp_manager_info.is_running_rapp(rapp) self._selected_rapp = rapp self._dialog = QtRappDialog(self._widget, rapp, self._qt_rapp_manager_info.start_rapp, self._qt_rapp_manager_info.stop_rapp, is_running) self._dialog.show() def _rapp_double_click(self, item): running_rapps = self._qt_rapp_manager_info.get_running_rapps() if len(running_rapps) > 0: names = [r['display_name'] for r in running_rapps.values()] show_message(self._widget, "Error", "Rapp %s are already running" % names) else: self._start_rapp() def _start_rapp(self): result = self._qt_rapp_manager_info.start_rapp( self._selected_rapp['name'], [], self._selected_rapp['public_parameters']) show_message(self._widget, str(result.started), result.message) self._selected_rapp = None return result def _stop_rapp(self): result = self._qt_rapp_manager_info.stop_rapp() show_message(self._widget, str(result.stopped), result.message) self._selected_rapp = None return result
class ModelLogger: """ Convenience class for logging data. """ def __init__(self): """ Initializes the ModelLogger. """ self.__log_model = QStandardItemModel(0, 4, None) self.__log_model.setHorizontalHeaderLabels(["type", "date", "location", "message"]) def log(self, type, date, location, message): """ Adds a log entry to the log_model. :param type: the type of the log_entry :type type: str :param date: the time of the log_entry :type date: Time :param location: the location, were the fault/info/... occured :type location: str :param message: the message of the log_entry :type message: str """ self.__log_model.insertRow(0) self.__log_model.setData(self.__log_model.index(0, 0), str(type)) self.__log_model.setData(self.__log_model.index(0, 1), time.strftime("%d.%m-%H:%M:%S", time.localtime(int(str(date)) / 1000000000))) self.__log_model.setData(self.__log_model.index(0, 2), str(location)) self.__log_model.setData(self.__log_model.index(0, 3), str(message)) def get_representation(self): """ Returns the log as a QStandartItemModel :returns: the log-model :rtype: QStandartItemModel """ return self.__log_model
class NodeSelectorWidget(QWidget): _COL_NAMES = ['Node'] # public signal _sig_node_selected = Signal(str) def __init__(self): super(NodeSelectorWidget, self).__init__() self.stretch = None ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ui/node_selector.ui') loadUi(ui_file, self) # Setup treeview and models self._std_model = QStandardItemModel() self._node_selector_view.setModel(self._std_model) self._rootitem = self._std_model.invisibleRootItem() self._nodes_previous = None # Calling this method updates the list of the node. # Initially done only once. self._update_nodetree() # Setting slot for when user clickes on QTreeView. selectionModel = self._node_selector_view.selectionModel() selectionModel.selectionChanged.connect(self._selection_changed_slot) #TODO(Isaac): Needs auto-update function enabled, once another function # that updates node tree with maintaining collapse/expansion # state. http://goo.gl/GuwYp can be a help. # self.timer = QTimer() # self.timer.timeout.connect(self._refresh_nodes) # self.timer.start(5000) # 5sec interval is fast enough. self._collapse_button.pressed.connect( self._node_selector_view.collapseAll) self._expand_button.pressed.connect(self._node_selector_view.expandAll) def _selection_changed_slot(self, selected, deselected): """ Overriden from QItemSelectionModel. :type new_item_select: QItemSelection :type old_item_select: QItemSelection """ index_current = self._node_selector_view.selectionModel().currentIndex( ) rospy.logdebug( '_selection_changed_slot row=%d col=%d data=%s ' + 'data.parent=%s child(0, 0)=%s', index_current.row(), index_current.column(), index_current.data(Qt.DisplayRole), index_current.parent().data(Qt.DisplayRole), index_current.child(0, 0).data(Qt.DisplayRole)) if not index_current.child(0, 0).data(Qt.DisplayRole) == None: return # Meaning the tree has no nodes. # get the text of the selected item node_name_selected = self.get_full_grn_recur(index_current, '') rospy.logdebug('_selection_changed_slot node_name_selected=%s', node_name_selected) self._sig_node_selected.emit(node_name_selected) def get_full_grn_recur(self, model_index, str_grn): """ Create full path format of GRN (Graph Resource Names, see http://www.ros.org/wiki/Names). An example: /wide_stereo/left/image_color/compressed Bulid GRN by recursively transcending parents & children of QModelIndex instance. Upon its very 1st call, the argument is the index where user clicks on on the view object (here QTreeView is used but should work with other View). str_grn can be 0-length string. :type model_index: QModelIndex :type str_grn: str :param str_grn: This could be an incomplete or a complete GRN format. """ #TODO(Isaac) Consider moving this to rqt_py_common. rospy.logdebug('get_full_grn_recur in str=%s', str_grn) if model_index.data(Qt.DisplayRole) == None: return str_grn str_grn = '/' + str(model_index.data(Qt.DisplayRole)) + str_grn rospy.logdebug('get_full_grn_recur out str=%s', str_grn) return self.get_full_grn_recur(model_index.parent(), str_grn) def _update_nodetree(self): """ """ #TODO(Isaac): 11/25/2012 dynamic_reconfigure only returns params that # are associated with nodes. In order to handle independent # params, different approach needs taken. try: nodes = dynamic_reconfigure.find_reconfigure_services() except rosservice.ROSServiceIOException as e: rospy.logerr("Reconfigure GUI cannot connect to master.") raise e # TODO Make sure 'raise' returns/finalizes this func. if not nodes == self._nodes_previous: paramname_prev = '' paramitem_top_prev = None i_debug = 0 for node_name_grn in nodes: p = ParameterItem(node_name_grn) p.set_param_name(node_name_grn) names = p.get_param_names() i_debug += 1 rospy.logdebug('_update_nodetree i=%d names=%s', i_debug, names) self._add_tree_node(p, self._rootitem, names) def _add_tree_node(self, param_item_full, stditem_parent, child_names_left): """ Evaluate current node and the previous node on the same depth. If the name of both nodes is the same, current node instance is ignored. If not, the current node gets added to the same parent node. At the end, this function gets called recursively going down 1 level. :type param_item_full: ParameterItem :type stditem_parent: QStandardItem. :type child_names_left: List of str :param child_names_left: List of strings that is sorted in hierarchical order of params. """ #TODO(Isaac): Consider moving to rqt_py_common. name_curr = child_names_left.pop(0) stditem_curr = ParameterItem(param_item_full.get_raw_param_name()) # item at the bottom is your most recent node. row_index_parent = stditem_parent.rowCount() - 1 # Obtain and instantiate prev node in the same depth. name_prev = '' stditem_prev = None if not stditem_parent.child(row_index_parent) == None: stditem_prev = stditem_parent.child(row_index_parent) name_prev = stditem_prev.text() stditem = None if name_prev != name_curr: stditem_curr.setText(name_curr) stditem_parent.appendRow(stditem_curr) stditem = stditem_curr else: stditem = stditem_prev rospy.logdebug( 'add_tree_node 1 name_curr=%s ' + '\n\t\t\t\t\tname_prev=%s row_index_parent=%d', name_curr, name_prev, row_index_parent) if len(child_names_left) != 0: #TODO: View & Model are closely bound here. Ideally isolate this 2. # Maybe we should split into 2 classs, 1 handles view, # the other does model. self._add_tree_node(param_item_full, stditem, child_names_left) def _refresh_nodes(self): #TODO(Isaac) In the future, do NOT remove all nodes. Instead, # remove only the ones that are gone. And add new ones too. model = self._rootitem if model.hasChildren(): row_count = model.rowCount() model.removeRows(0, row_count) rospy.logdebug("ParamWidget _refresh_nodes row_count=%s", row_count) self._update_nodetree() def close_node(self): rospy.logdebug(" in close_node")
class TreeviewWidgetSelectProve(QWidget): def __init__(self): super(TreeviewWidgetSelectProve, self).__init__() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_prove'), 'resource', #'treeview_non_custom.ui') # Works with pyqt. 'treeview_with_custom.ui') # No good. #loadUi(ui_file, self) loadUi(ui_file, self, {'CustomQTreeview': CustomQTreeview}) self._std_model = QStandardItemModel() self._rootitem = self._std_model.invisibleRootItem() item_r_1 = QStandardItem("r1") self._rootitem.appendRow(item_r_1) print('_rootitem index={}'.format(self._rootitem.index())) self.treeview.setModel(self._std_model) self.selectionModel = self.treeview.selectionModel() self.selectionModel.selectionChanged.connect( self._selection_changed_slot) print('del/sel?\tde/sel index\tde/sel.row\tde/sel.dat\tparent\tinternal id') self.show() def _selection_changed_slot(self, selected, deselected): """ Receives args from signal QItemSelectionModel.selectionChanged. :type selected: QItemSelection :type deselected: QItemSelection """ self._test_sel_index(selected, deselected) def _test_sel_index(self, selected, deselected): src_model = self._std_model index_current = None index_deselected = None index_parent_sel = None index_parent_desel = None curr_qstd_item = None indexes = selected.indexes() del_or_sel = 'Sel' index_internalid = -1 if len(indexes) > 0: index_internalid = selected.indexes()[0].internalId() # # Trying many approaches to get the right qindex # # Approach-1 index_current = selected.indexes()[0] # # Approach-2 # index_current_from_indexes = selected.indexes()[0] # index_current = src_model.index(index_current_from_indexes.row(), # 0, QModelIndex()) # 0, index_current_from_indexes) # index_current = self.selectionModel.currentIndex() index_parent_sel = index_current.parent() curr_qstd_item = src_model.itemFromIndex( # index_parent) index_current) elif len(deselected.indexes()) > 0: index_internalid = deselected.indexes()[0].internalId() del_or_sel = 'Desel' index_deselected = self.selectionModel.currentIndex() index_parent_desel = index_deselected.parent() curr_qstd_item = src_model.itemFromIndex(index_deselected) tabular_format = '{}\t{}\t{}\t{}\t{}\t{}' if len(indexes) > 0: print(tabular_format.format( del_or_sel, index_current, index_current.row(), index_current.data(Qt.DisplayRole).toString(), #curr_qstd_item, #curr_qstd_item.data(Qt.DisplayRole), index_parent_sel, #index_parent_sel.data(Qt.DisplayRole), index_internalid)) elif len(deselected.indexes()) > 0: print(tabular_format.format( del_or_sel, index_deselected, index_deselected.row(), index_deselected.data(Qt.DisplayRole).toString(), #curr_qstd_item, # curr_qstd_item.data(), index_parent_desel, # index_parent_desel.data(Qt.DisplayRole), index_internalid)) self.selectionModel.select(index_deselected, QItemSelectionModel.Deselect)
class LaunchWidget(QDialog): '''#TODO: comment ''' # To be connected to PluginContainerWidget sig_sysmsg = Signal(str) def __init__(self, parent): ''' @type parent: LaunchMain ''' super(LaunchWidget, self).__init__() self._parent = parent self._config = None #TODO: should be configurable from gui self._port_roscore = 11311 self._run_id = None self._rospack = rospkg.RosPack() ui_file = os.path.join(self._rospack.get_path('rqt_launch'), 'resource', 'launch_widget.ui') loadUi(ui_file, self) # row=0 allows any number of rows to be added. self._datamodel = QStandardItemModel(0, 1) master_uri = rosenv.get_master_uri() rospy.loginfo('LaunchWidget master_uri={}'.format(master_uri)) self._delegate = NodeDelegate(master_uri, self._rospack) self._treeview.setModel(self._datamodel) self._treeview.setItemDelegate(self._delegate) # NodeController used in controller class for launch operation. self._node_controllers = [] self._pushbutton_start_all.clicked.connect(self._parent.start_all) self._pushbutton_stop_all.clicked.connect(self._parent.stop_all) # Bind package selection with .launch file selection. self._combobox_pkg.currentIndexChanged[str].connect( self._refresh_launchfiles) # Bind a launch file selection with launch GUI generation. self._combobox_launchfile_name.currentIndexChanged[str].connect( self._load_launchfile_slot) self._update_pkgs_contain_launchfiles() # Used for removing previous nodes self._num_nodes_previous = 0 def _load_launchfile_slot(self, launchfile_name): # Not yet sure why, but everytime combobox.currentIndexChanged occurs, # this method gets called twice with launchfile_name=='' in 1st call. if launchfile_name == None or launchfile_name == '': return _config = None rospy.logdebug('_load_launchfile_slot launchfile_name={}'.format( launchfile_name)) try: _config = self._create_launchconfig(launchfile_name, self._port_roscore) #TODO: folder_name_launchfile should be able to specify arbitrarily # _create_launchconfig takes 3rd arg for it. except IndexError as e: msg = 'IndexError={} launchfile={}'.format(e.message, launchfile_name) rospy.logerr(msg) self.sig_sysmsg.emit(msg) return except RLException as e: msg = 'RLException={} launchfile={}'.format(e.message, launchfile_name) rospy.logerr(msg) self.sig_sysmsg.emit(msg) return self._create_widgets_for_launchfile(_config) def _create_launchconfig(self, launchfile_name, port_roscore=11311, folder_name_launchfile='launch'): ''' @rtype: ROSLaunchConfig @raises RLException: raised by roslaunch.config.load_config_default. ''' pkg_name = self._combobox_pkg.currentText() try: launchfile = os.path.join(self._rospack.get_path(pkg_name), folder_name_launchfile, launchfile_name) except IndexError as e: raise RLException('IndexError: {}'.format(e.message)) try: launch_config = roslaunch.config.load_config_default([launchfile], port_roscore) except rospkg.common.ResourceNotFound as e: raise RLException('ResourceNotFound: {}'.format(e.message)) except RLException as e: raise e return launch_config def _create_widgets_for_launchfile(self, config): self._config = config # Delete old nodes' GUIs. self._node_controllers = [] # These lines seem to remove indexWidgets previously set on treeview. # Per suggestion in API doc, we are not using reset(). Instead, # using 2 methods below without any operation in between, which # I suspect might be inproper. # http://qt-project.org/doc/qt-4.8/qabstractitemmodel.html#reset self._datamodel.beginResetModel() self._datamodel.endResetModel() # Need to store the num of nodes outside of the loop -- this will # be used for removing excessive previous node rows. order_xmlelement = 0 # Loop per xml element for order_xmlelement, node in enumerate(self._config.nodes): proxy = NodeProxy(self._run_id, self._config.master.uri, node) # TODO: consider using QIcon.fromTheme() status_label = StatusIndicator() qindex_nodewidget = self._datamodel.index(order_xmlelement, 0, QModelIndex()) node_widget = self._delegate.create_node_widget(qindex_nodewidget, proxy.config, status_label) #TODO: Ideally find a way so that we don't need this block. #BEGIN If these lines are missing, widget won't be shown either. std_item = QStandardItem( #node_widget.get_node_name() ) self._datamodel.setItem(order_xmlelement, 0, std_item) #END If these lines are missing, widget won't be shown either. self._treeview.setIndexWidget(qindex_nodewidget, node_widget) node_controller = NodeController(proxy, node_widget) self._node_controllers.append(node_controller) node_widget.connect_start_stop_button( \ node_controller.start_stop_slot) rospy.logdebug('loop #%d proxy.config.namespace=%s ' + 'proxy.config.name=%s', order_xmlelement, proxy.config.namespace, proxy.config.name) self._num_nodes_previous = order_xmlelement self._parent.set_node_controllers(self._node_controllers) def _update_pkgs_contain_launchfiles(self): ''' Inspired by rqt_msg.MessageWidget._update_pkgs_contain_launchfiles ''' packages = sorted([pkg_tuple[0] for pkg_tuple in RqtRoscommUtil.iterate_packages('launch')]) self._package_list = packages rospy.logdebug('pkgs={}'.format(self._package_list)) self._combobox_pkg.clear() self._combobox_pkg.addItems(self._package_list) self._combobox_pkg.setCurrentIndex(0) def _refresh_launchfiles(self, package=None): ''' Inspired by rqt_msg.MessageWidget._refresh_msgs ''' if package is None or len(package) == 0: return self._launchfile_instances = [] # Launch[] #TODO: RqtRoscommUtil.list_files's 2nd arg 'subdir' should NOT be # hardcoded later. _launch_instance_list = RqtRoscommUtil.list_files(package, 'launch') rospy.logdebug('_refresh_launches package={} instance_list={}'.format( package, _launch_instance_list)) self._launchfile_instances = [x.split('/')[1] for x in _launch_instance_list] self._combobox_launchfile_name.clear() self._combobox_launchfile_name.addItems(self._launchfile_instances) def save_settings(self, plugin_settings, instance_settings): # instance_settings.set_value('splitter', self._splitter.saveState()) pass def restore_settings(self, plugin_settings, instance_settings): # if instance_settings.contains('splitter'): # self._splitter.restoreState(instance_settings.value('splitter')) # else: # self._splitter.setSizes([100, 100, 200]) pass
class MoveitWidget(QWidget): """#TODO: comment """ # To be connected to PluginContainerWidget sig_sysmsg = None sig_param = Signal(bool, str) # param name emitted sig_node = Signal(bool, str) # param name emitted _SPLITTER_H = 'splitter_horizontal' def __init__(self, parent, plugin_context): """ @type parent: MoveitMain """ self._nodes_monitored = ['/move_group'] self._selected_topics = [('/pointcloud', 'sensor_msgs/PointCloud'), ('/pointcloud2', 'sensor_msgs/PointCloud2'), ('/image', 'sensor_msgs/Image'), ('/camera_info', 'sensor_msgs/CameraInfo')] self._params_monitored = ['/robot_description', '/robot_description_semantic'] super(MoveitWidget, self).__init__() self._parent = parent self._plugin_context = plugin_context self._refresh_rate = 5 # With default value self._rospack = rospkg.RosPack() ui_file = os.path.join(self._rospack.get_path('rqt_moveit'), 'resource', 'moveit_top.ui') loadUi(ui_file, self, {'TopicWidget': TopicWidget}) # Custom widget classes don't show in QSplitter when they instantiated # in .ui file and not explicitly added to QSplitter like this. Thus # this is a workaround. self._splitter.addWidget(self._widget_topic) self._spinbox_refreshrate.valueChanged.connect( self._update_refreshrate) # Show default ref rate on QSpinbox self._spinbox_refreshrate.setValue(self._refresh_rate) # Monitor node self._is_checking_nodes = True self._node_qitems = {} self._node_monitor_thread = self._init_monitor_nodes( self._nodes_monitored) self._node_monitor_thread.start() #TODO: connect sys msg for nodes. # topic to show # Delegate GUI functionality to rqt_topic.TopicWidget. self._widget_topic.set_selected_topics(self._selected_topics) self._widget_topic.set_topic_specifier(TopicWidget.SELECT_BY_MSGTYPE) self._widget_topic.start() # To connect signal in a widget to PluginContainerWidget. #TODO: In this way, Signal from only one instance is hooked. # Not a good design at all. self.sig_sysmsg = self._widget_topic.sig_sysmsg # Init monitoring parameters. self._is_checking_params = True self._param_qitems = {} _col_names_paramtable = ['Param name', 'Found on Parameter Server?'] self._param_check_thread = self._init_monitor_parameters( self._params_monitored, _col_names_paramtable) self._param_check_thread.start() def _init_monitor_nodes(self, nodes_monitored): """ @type params_monitored: str[] @rtype: Thread """ self._node_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._node_datamodel.invisibleRootItem() self._view_nodes.setModel(self._node_datamodel) node_monitor_thread = Thread(target=self._check_nodes_alive, args=(self.sig_node, self._nodes_monitored)) # self._node_monitor_thread = NodeMonitorThread(self, self.sig_node, # nodes_monitored) self.sig_node.connect(self._update_output_nodes) return node_monitor_thread def _check_nodes_alive(self, signal, nodes_monitored): """ Working as a callback of Thread class, this method keeps looping to watch if the nodes whose names are passed exist and emits signal per each node. Notice that what MoveitWidget._check_nodes_alive & MoveitWidget._check_params_alive do is very similar, but since both of them are supposed to be passed to Thread class, there might not be a way to generalize these 2. @param signal: Signal(bool, str) @type nodes_monitored: str[] """ while self._is_checking_nodes: rosnode_dynamically_loaded = __import__('rosnode') #from rosnode import rosnode_ping for nodename in nodes_monitored: #TODO: rosnode_ping prints when the node is not found. # Currently I have no idea how to capture that from here. try: #is_node_running = rosnode_ping(nodename, 1) is_node_running = rosnode_dynamically_loaded.rosnode_ping( nodename, 1) except rosnode_dynamically_loaded.ROSNodeIOException as e: #TODO: Needs to be indicated on GUI # (eg. PluginContainerWidget) rospy.logerr(e.message) is_node_running = False signal.emit(is_node_running, nodename) rospy.logdebug('_update_output_nodes') del rosnode_dynamically_loaded time.sleep(self._refresh_rate) def _init_monitor_parameters(self, params_monitored, _col_names_paramtable=None): """ @type params_monitored: str[] """ self._params_monitored = params_monitored self._param_datamodel = QStandardItemModel(0, 2) self._root_qitem = self._param_datamodel.invisibleRootItem() self._view_params.setModel(self._param_datamodel) # Names of header on the QTableView. if not _col_names_paramtable: _col_names_paramtable = ['Param name', 'Found on Parameter Server?'] self._param_datamodel.setHorizontalHeaderLabels(_col_names_paramtable) self.sig_param.connect(self._update_output_parameters) param_check_thread = Thread(target=self._check_params_alive, args=(self.sig_param, self._params_monitored)) return param_check_thread def _update_output_nodes(self, is_node_running, node_name): """ Slot for signals that tell nodes existence. @type is_node_running: bool @type node_name: str """ #TODO: What this method does is exactly the same with # monitor_parameters. Unify them. rospy.logdebug('is_node_running={} par_name={}'.format(is_node_running, node_name)) node_name = str(node_name) node_qitem = None if not node_name in self._node_qitems: node_qitem = QStandardItem(node_name) self._node_qitems[node_name] = node_qitem self._node_datamodel.appendRow(node_qitem) else: # qsitem with the node name already exists. node_qitem = self._node_qitems[str(node_name)] qindex = self._node_datamodel.indexFromItem(node_qitem) _str_node_running = 'Not running' if is_node_running: _str_node_running = 'Running' qitem_node_status = QStandardItem(_str_node_running) self._node_datamodel.setItem(qindex.row(), 1, qitem_node_status) def _check_params_alive(self, signal, params_monitored): """ Working as a callback of Thread class, this method keeps looping to watch if the params whose names are passed exist and emits signal per each node. Notice that what MoveitWidget._check_nodes_alive & MoveitWidget._check_params_alive do is very similar, but since both of them are supposed to be passed to Thread class, there might not be a way to generalize these 2. @type signal: Signal(bool, str) @param_name signal: emitting a name of the parameter that's found. @type params_monitored: str[] """ while self._is_checking_params: # self._is_checking_params only turns to false when the plugin # shuts down. has_param = False for param_name in params_monitored: is_rosmaster_running = RqtRoscommUtil.is_roscore_running() try: if is_rosmaster_running: # Only if rosmaster is running, check if the parameter # exists or not. has_param = rospy.has_param(param_name) except rospy.exceptions.ROSException as e: self.sig_sysmsg.emit( 'Exception upon rospy.has_param {}'.format(e.message)) signal.emit(has_param, param_name) rospy.loginfo('has_param {}, check_param_alive: {}'.format( has_param, param_name)) time.sleep(self._refresh_rate) def _update_output_parameters(self, has_param, param_name): """ Slot @type has_param: bool @type param_name: str """ rospy.logdebug('has_param={} par_name={}'.format(has_param, param_name)) param_name = str(param_name) param_qitem = None if not param_name in self._param_qitems: param_qitem = QStandardItem(param_name) self._param_qitems[param_name] = param_qitem self._param_datamodel.appendRow(param_qitem) else: # qsitem with the param name already exists. param_qitem = self._param_qitems[str(param_name)] qindex = self._param_datamodel.indexFromItem(param_qitem) _str_param_found = 'No' if has_param: _str_param_found = 'Yes' qitem_param_status = QStandardItem(_str_param_found) self._param_datamodel.setItem(qindex.row(), 1, qitem_param_status) self._view_params.resizeColumnsToContents() def _update_refreshrate(self, refresh_rate): """ Slot @type refresh_rate: int """ self._refresh_rate = refresh_rate def save_settings(self, plugin_settings, instance_settings): instance_settings.set_value(self._SPLITTER_H, self._splitter.saveState()) def restore_settings(self, plugin_settings, instance_settings): if instance_settings.contains(self._SPLITTER_H): self._splitter.restoreState(instance_settings.value( self._SPLITTER_H)) else: self._splitter.setSizes([100, 100, 200]) pass def shutdown(self): """ Overridden. Close threads. @raise RuntimeError: """ try: #self._node_monitor_thread.join() # No effect self._is_checking_nodes = False self._node_monitor_thread = None #self._param_check_thread.join() self._is_checking_params = False self._param_check_thread = None except RuntimeError as e: rospy.logerr(e) raise e
def __init__(self, parent=None): # FIXME: why is this not working? should be the same as the following line... #super(MessageTreeModel, self).__init__(parent) QStandardItemModel.__init__(self, parent)
def _empty_item_model(): return QStandardItemModel()