def __init__(self, context): super(QuestionDialogPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('QuestionDialogPlugin') font_size = rospy.get_param("~font_size", 40) # Create QWidget self._widget = QWidget() self._widget.setFont(QFont("Times", font_size, QFont.Bold)) self._layout = QVBoxLayout(self._widget) self._text_browser = QTextBrowser(self._widget) self._layout.addWidget(self._text_browser) self._button_layout = QGridLayout() self._layout.addLayout(self._button_layout) # layout = QVBoxLayout(self._widget) # layout.addWidget(self.button) self._widget.setObjectName('QuestionDialogPluginUI') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) # Setup service provider self.service = rospy.Service('question_dialog', QuestionDialog, self.service_callback) self.response_ready = False self.response = None self.buttons = [] self.text_label = None self.text_input = None self.connect(self._widget, SIGNAL("update"), self.update) self.connect(self._widget, SIGNAL("timeout"), self.timeout)
class RosMsgView(QGroupBox): def __init__(self,parent,name,topic_name,topic_type,topic_fields): super(RosMsgView,self).__init__(name,parent) self.topic_name = topic_name self.topic_type = topic_type self.topic_fields = topic_fields self.ref_dict = {} self.layout = QGridLayout() self.__populate_self() self.subscriber = RosHelper.create_subscriber_from_type(self.topic_name,self.topic_type,self.onmsg) def __populate_self(self): i = 1 if len(self.topic_fields) == 0: fields = RosHelper.get_all_msg_fields(self.topic_type) else: fields = self.topic_fields for field in fields: self.ref_dict[field] = QLabel("None",self) self.layout.addWidget(QLabel(field,self),i,1) self.layout.addWidget(self.ref_dict[field],i,2) i+=1 self.setLayout(self.layout) def onmsg(self,msg): # loop msg with topic field and for topic_field in self.topic_fields: r = msg lbl = self.ref_dict[topic_field] for subfields in topic_field.split(".")[1:]: r = getattr(r,subfields) lbl.setText(str(r))
class RosMsgView(QGroupBox): def __init__(self, parent, name, topic_name, topic_type, topic_fields): super(RosMsgView, self).__init__(name, parent) self.topic_name = topic_name self.topic_type = topic_type self.topic_fields = topic_fields self.ref_dict = {} self.layout = QGridLayout() self.__populate_self() self.subscriber = RosHelper.create_subscriber_from_type( self.topic_name, self.topic_type, self.onmsg) def __populate_self(self): i = 1 if len(self.topic_fields) == 0: fields = RosHelper.get_all_msg_fields(self.topic_type) else: fields = self.topic_fields for field in fields: self.ref_dict[field] = QLabel("None", self) self.layout.addWidget(QLabel(field, self), i, 1) self.layout.addWidget(self.ref_dict[field], i, 2) i += 1 self.setLayout(self.layout) def onmsg(self, msg): # loop msg with topic field and for topic_field in self.topic_fields: r = msg lbl = self.ref_dict[topic_field] for subfields in topic_field.split(".")[1:]: r = getattr(r, subfields) lbl.setText(str(r))
def __init__(self, parent, name, topic_name, topic_type, topic_fields): super(RosMsgView, self).__init__(name, parent) self.topic_name = topic_name self.topic_type = topic_type self.topic_fields = topic_fields self.ref_dict = {} self.layout = QGridLayout() self.__populate_self() self.subscriber = RosHelper.create_subscriber_from_type( self.topic_name, self.topic_type, self.onmsg)
def beginRosLabel(self,obj): pm,lm = self.__get_immediate_parent() fr = QFrame(pm) layout = QGridLayout() nlb = QLabel(obj.label_name + ":",fr) nlb.setToolTip(obj.topic_name) layout.addWidget(nlb,1,1) layout.addWidget(RosLabel(fr,obj.label_name,obj.topic_name,obj.topic_type,obj.topic_field),1,2) fr.setLayout(layout) lm.addWidget(fr)
def __init__(self, context, actions): super(ActionClientContainerWidget, self).__init__() grid = QGridLayout() grid.setSpacing(1) MAX_COLUMNS = 2 self.setObjectName('ActionClientContainerWidget') self.clear_button = QPushButton("Clear all") self.clear_button.clicked[bool].connect(self._handle_clear_clicked) grid.addWidget(self.clear_button, 0, 0) self.widgets = [] row = 1 column = 0 for k in sorted(actions.keys()): action_name = k widget = ActionClientWidget(context, action_name, actions[k]) grid.addWidget(widget, row, column) self.widgets.append(widget) column += 1 if column >= MAX_COLUMNS: row += 1 column = 0 self.setLayout(grid)
def __init__(self,parent,name,topic_name,topic_type,topic_fields): super(RosMsgView,self).__init__(name,parent) self.topic_name = topic_name self.topic_type = topic_type self.topic_fields = topic_fields self.ref_dict = {} self.layout = QGridLayout() self.__populate_self() self.subscriber = RosHelper.create_subscriber_from_type(self.topic_name,self.topic_type,self.onmsg)
def beginGroup(self, obj): parent, layout = self.__get_immediate_parent() panel = QGroupBox(obj.name, parent) if obj.layout == "grid": l = QGridLayout() elif obj.layout == "vertical": l = QVBoxLayout() else: l = QHBoxLayout() self.__increase_nesting_level(panel, l)
def onCreate(self, param): layout = QGridLayout(self) layout.setContentsMargins(2, 2, 2, 2) self._rospack = rospkg.RosPack() self._model = MessageDataModel() self._proxy_model = MessageProxyModel() self._proxy_model.setSourceModel(self._model) self.__widget = ConsoleWidget(self._proxy_model, self._rospack) layout.addWidget(self.__widget, 0, 0, 0, 0) # queue to store incoming data which get flushed periodically to the model # required since QSortProxyModel can not handle a high insert rate self._message_queue = [] self._mutex = QMutex() self._timer = QTimer() self._timer.timeout.connect(self.insert_messages) self._timer.start(100) self._subscriber = None self._topic = '/rosout_agg' self._subscribe(self._topic)
def __init__(self, updater, config): """ :param config: defined in dynamic_reconfigure.client.Client """ super(GroupWidget, self).__init__() self.state = config['state'] self.name = config['name'] self.tab_bar = None # Every group can have one tab bar self.tab_bar_shown = False self.grid = QGridLayout() self.updater = updater self.editor_widgets = [] self.add_widgets(config) # Labels should not stretch self.grid.setColumnStretch(1,1) self.setLayout(self.grid)
def buildButtonGrid(labelTextArray, numColumns): ''' Creates a grid of QPushButton widgets. They will be @param labelTextArray: Button labels. @type labelTextArray: [string] @param numColumns: The desired width of the button grid. @type numColumns: int @return: 1. a grid layout with the button objects inside. 2. a dictionary mapping button labels to button objects. @rtype: QGridLayout ''' buttonLayout = QGridLayout(); # Compute number of button rows: numRows = len(labelTextArray) / numColumns; # If this number of rows leaves a few buttons left over (< columnNum), # then add a row for those: if (len(labelTextArray) % numColumns) > 0: numRows += 1; buttonDict = {} row = 0; col = 0; for buttonLabel in labelTextArray: button = QPushButton(buttonLabel); buttonDict[buttonLabel] = button; buttonLayout.addWidget(button, row, col); col += 1; if (col > (numColumns - 1)): col = 0; row += 1; return (buttonLayout, buttonDict);
def beginRosLabel(self, obj): pm, lm = self.__get_immediate_parent() fr = QFrame(pm) layout = QGridLayout() nlb = QLabel(obj.label_name + ":", fr) nlb.setToolTip(obj.topic_name) layout.addWidget(nlb, 1, 1) layout.addWidget( RosLabel(fr, obj.label_name, obj.topic_name, obj.topic_type, obj.topic_field), 1, 2) fr.setLayout(layout) lm.addWidget(fr)
def __init__(self): super(NodeWidgetsContainer, self).__init__() yaml_file = rospy.get_param("~config_file") stream = open(yaml_file, "r") nodes = yaml.load(stream) rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('mcr_event_gui'), 'ros', 'resources', 'NodeWidgetsContainer.ui') loadUi(ui_file, self) grid = QGridLayout() grid.setSpacing(1) MAX_COLUMNS = 2 self.setObjectName('NodeWidgetsContainer') self.clear_button = QPushButton("Clear all") self.clear_button.clicked[bool].connect(self._handle_clear_clicked) self.stop_button = QPushButton("Stop all") self.stop_button.clicked[bool].connect(self._handle_stop_clicked) grid.addWidget(self.clear_button, 0, 0) grid.addWidget(self.stop_button, 0, 1) self.widgets = [] row = 1 column = 0 for k in sorted(nodes.keys()): node_name = k widget = NodeEventsWidget(node_name, nodes[k]) width = widget.width() height = widget.height() grid.addWidget(widget, row, column) grid.setColumnMinimumWidth(column, width) grid.setRowMinimumHeight(row, height) self.widgets.append(widget) column += 1 if column >= MAX_COLUMNS: row += 1 column = 0 self.setLayout(grid)
def setup_group_frame(self, group): layout = QVBoxLayout() # grid for buttons for named targets grid = QGridLayout() grid.setSpacing(1) self.button_group = QButtonGroup(self) row = 0 column = 0 named_targets = self.get_named_targets(group) for target in named_targets: button = QPushButton(target) self.button_group.addButton(button) grid.addWidget(button, row, column) column += 1 if column >= self.MAX_COLUMNS: row += 1 column = 0 self.button_group.buttonClicked.connect(self._handle_button_clicked) # grid for show joint value and move arm buttons/text field joint_values_grid = QGridLayout() joint_values_grid.setSpacing(1) button_show_joint_values = QPushButton('Current Joint Values') button_show_joint_values.clicked[bool].connect( self._handle_show_joint_values_clicked) line_edit = QLineEdit() self.text_joint_values.append(line_edit) button_move_to = QPushButton('Move to') button_move_to.clicked[bool].connect(self._handle_move_to_clicked) joint_values_grid.addWidget(button_show_joint_values, 0, 1) joint_values_grid.addWidget(line_edit, 0, 2) joint_values_grid.addWidget(button_move_to, 0, 3) layout.addLayout(grid) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) layout.addWidget(line) layout.addLayout(joint_values_grid) frame = QFrame() frame.setLayout(layout) return frame
def _set_add_rocon_master(self): if self._connect_dlg_isValid: console.logdebug("Dialog is live!!") self._connect_dlg.done(0) #dialog self._connect_dlg = QDialog(self._widget_main) self._connect_dlg.setWindowTitle("Add Ros Master") self._connect_dlg.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) self._connect_dlg.setMinimumSize(350, 0) # dlg_rect = self._connect_dlg.geometry() #dialog layout ver_layout = QVBoxLayout(self._connect_dlg) ver_layout.setContentsMargins(9, 9, 9, 9) #param layout text_grid_sub_widget = QWidget() text_grid_layout = QGridLayout(text_grid_sub_widget) text_grid_layout.setColumnStretch(1, 0) text_grid_layout.setRowStretch(2, 0) #param 1 title_widget1 = QLabel("MASTER_URI: ") context_widget1 = QTextEdit() context_widget1.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) context_widget1.setMinimumSize(0, 30) context_widget1.append(self.master_uri) #param 2 title_widget2 = QLabel("HOST_NAME: ") context_widget2 = QTextEdit() context_widget2.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) context_widget2.setMinimumSize(0, 30) context_widget2.append(self.host_name) #add param text_grid_layout.addWidget(title_widget1) text_grid_layout.addWidget(context_widget1) text_grid_layout.addWidget(title_widget2) text_grid_layout.addWidget(context_widget2) #add param layout ver_layout.addWidget(text_grid_sub_widget) #button layout button_hor_sub_widget = QWidget() button_hor_layout = QHBoxLayout(button_hor_sub_widget) uri_text_widget = context_widget1 host_name_text_widget = context_widget2 #check box use_env_var_check = QCheckBox("Use environment variables") use_env_var_check.setCheckState(Qt.Unchecked) def set_use_env_var(data, text_widget1, text_widget2): if data == Qt.Unchecked: text_widget1.setText(self.master_uri) text_widget2.setText(self.host_name) elif data == Qt.Checked: self.master_uri = str(text_widget1.toPlainText()) self.host_name = str(text_widget2.toPlainText()) text_widget1.setText(self.env_master_uri) text_widget2.setText(self.env_host_name) def check_event(data): set_use_env_var(data, context_widget1, context_widget2) use_env_var_check.stateChanged.connect(check_event) ver_layout.addWidget(use_env_var_check) #button btn_call = QPushButton("Add") btn_cancel = QPushButton("Cancel") btn_call.clicked.connect(lambda: self._connect_dlg.done(0)) btn_call.clicked.connect(lambda: self._add_rocon_master( uri_text_widget, host_name_text_widget)) btn_cancel.clicked.connect(lambda: self._connect_dlg.done(0)) #add button button_hor_layout.addWidget(btn_call) button_hor_layout.addWidget(btn_cancel) #add button layout ver_layout.addWidget(button_hor_sub_widget) self._connect_dlg.setVisible(True) self._connect_dlg.finished.connect(self._destroy_connect_dlg) self._connect_dlg_isValid = True
class QuestionDialogPlugin(Plugin): def __init__(self, context): super(QuestionDialogPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('QuestionDialogPlugin') font_size = rospy.get_param("~font_size", 40) # Create QWidget self._widget = QWidget() self._widget.setFont(QFont("Times", font_size, QFont.Bold)) self._layout = QVBoxLayout(self._widget) self._text_browser = QTextBrowser(self._widget) self._layout.addWidget(self._text_browser) self._button_layout = QGridLayout() self._layout.addLayout(self._button_layout) # layout = QVBoxLayout(self._widget) # layout.addWidget(self.button) self._widget.setObjectName('QuestionDialogPluginUI') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) # Setup service provider self.service = rospy.Service('question_dialog', QuestionDialog, self.service_callback) self.response_ready = False self.response = None self.buttons = [] self.text_label = None self.text_input = None self.connect(self._widget, SIGNAL("update"), self.update) self.connect(self._widget, SIGNAL("timeout"), self.timeout) def shutdown_plugin(self): self.service.shutdown() def service_callback(self, req): self.response_ready = False self.request = req self._widget.emit(SIGNAL("update")) # Start timer against wall clock here instead of the ros clock. start_time = time.time() while not self.response_ready: if self.request != req: # The request got preempted by a new request. return QuestionDialogResponse(QuestionDialogRequest.PREEMPTED, "") if req.timeout != QuestionDialogRequest.NO_TIMEOUT: current_time = time.time() if current_time - start_time > req.timeout: self._widget.emit(SIGNAL("timeout")) return QuestionDialogResponse( QuestionDialogRequest.TIMED_OUT, "") time.sleep(0.2) return self.response def update(self): self.clean() req = self.request self._text_browser.setText(req.message) if req.type == QuestionDialogRequest.DISPLAY: # All done, nothing more too see here. self.response = QuestionDialogResponse( QuestionDialogRequest.NO_RESPONSE, "") self.response_ready = True elif req.type == QuestionDialogRequest.CHOICE_QUESTION: for index, options in enumerate(req.options): button = QPushButton(options, self._widget) button.clicked.connect(partial(self.handle_button, index)) row = index / 3 col = index % 3 self._button_layout.addWidget(button, row, col) self.buttons.append(button) elif req.type == QuestionDialogRequest.TEXT_QUESTION: self.text_label = QLabel("Enter here: ", self._widget) self._button_layout.addWidget(self.text_label, 0, 0) self.text_input = QLineEdit(self._widget) self.text_input.editingFinished.connect(self.handle_text) self._button_layout.addWidget(self.text_input, 0, 1) def timeout(self): self._text_browser.setText("Oh no! The request timed out.") self.clean() def clean(self): while self._button_layout.count(): item = self._button_layout.takeAt(0) item.widget().deleteLater() self.buttons = [] self.text_input = None self.text_label = None def handle_button(self, index): self.response = QuestionDialogResponse(index, "") self.clean() self.response_ready = True def handle_text(self): self.response = QuestionDialogResponse( QuestionDialogRequest.TEXT_RESPONSE, self.text_input.text()) self.clean() self.response_ready = True 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
class GroupWidget(QWidget): def __init__(self, updater, config): """ :param config: defined in dynamic_reconfigure.client.Client """ super(GroupWidget, self).__init__() self.state = config['state'] self.name = config['name'] self.tab_bar = None # Every group can have one tab bar self.tab_bar_shown = False self.grid = QGridLayout() self.updater = updater self.editor_widgets = [] self.add_widgets(config) # Labels should not stretch self.grid.setColumnStretch(1,1) self.setLayout(self.grid) def add_widgets(self, descr): i_debug = 0 for param in descr['parameters']: if param['edit_method']: widget = EnumEditor(self.updater, param) elif param['type'] in EDITOR_TYPES: widget = eval(EDITOR_TYPES[param['type']])(self.updater, param) self.editor_widgets.append(widget) rospy.logdebug('groups.add_widgets i=%d', i_debug) i_debug += 1 g_debug = 0 for name, group in descr['groups'].items(): if group['type'] == 'tab': widget = TabGroup(self, self.updater, group) elif group['type'] in _GROUP_TYPES.keys(): widget = eval(_GROUP_TYPES[group['type']])(self.updater, group) self.editor_widgets.append(widget) rospy.logdebug('groups.add_widgets g=%d', g_debug) g_debug += 1 for i, ed in enumerate(self.editor_widgets): ed.display(self.grid, i) def display(self, grid, row): #groups span across all columns grid.addWidget(self, row, 0, 1, -1) def update_group(self, config): self.state = config['state'] # TODO: should use config.keys but this method doesnt exist names = [name for name, v in config.items()] for widget in self.editor_widgets: if isinstance(widget, EditorWidget): if widget.name in names: widget.update_value(config[widget.name]) elif isinstance(widget, GroupWidget): cfg = find_cfg(config, widget.name) widget.update_group(cfg) def close(self): for w in self.editor_widgets: w.close()
def _setting_service(self): if self.is_setting_dlg_live: print "Dialog is live!!" self._setting_dlg.done(0) #dialog self._setting_dlg = QDialog(self._widget) self._setting_dlg.setWindowTitle("Seting Configuration") self._setting_dlg.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) self._setting_dlg.setMinimumSize(500, 0) dlg_rect = self._setting_dlg.geometry() #dialog layout ver_layout = QVBoxLayout(self._setting_dlg) ver_layout.setContentsMargins(9, 9, 9, 9) #param layout text_grid_sub_widget = QWidget() text_grid_layout = QGridLayout(text_grid_sub_widget) text_grid_layout.setColumnStretch(1, 0) text_grid_layout.setRowStretch(2, 0) #param 1 name = u"" title_widget1 = QLabel("Param1: ") context_widget1 = QTextEdit() context_widget1.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) context_widget1.setMinimumSize(0, 30) context_widget1.append("") #param 2 cancel = False title_widget2 = QLabel("Param2: ") context_widget2 = QTextEdit() context_widget2.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) context_widget2.setMinimumSize(0, 30) context_widget2.append("") #param 3 cancel = False title_widget3 = QLabel("Param2: ") context_widget3 = QTextEdit() context_widget3.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) context_widget3.setMinimumSize(0, 30) context_widget3.append("") #add param text_grid_layout.addWidget(title_widget1) text_grid_layout.addWidget(context_widget1) text_grid_layout.addWidget(title_widget2) text_grid_layout.addWidget(context_widget2) text_grid_layout.addWidget(title_widget3) text_grid_layout.addWidget(context_widget3) #add param layout ver_layout.addWidget(text_grid_sub_widget) #button layout button_hor_sub_widget = QWidget() button_hor_layout = QHBoxLayout(button_hor_sub_widget) params = {} params['param1'] = context_widget1 params['param2'] = context_widget2 params['param3'] = context_widget3 #button btn_call = QPushButton("Set") btn_cancel = QPushButton("Cancel") btn_call.clicked.connect(lambda: self._setting_dlg.done(0)) btn_call.clicked.connect(lambda: self._set_configuration(params)) btn_cancel.clicked.connect(lambda: self._setting_dlg.done(0)) #add button button_hor_layout.addWidget(btn_call) button_hor_layout.addWidget(btn_cancel) #add button layout ver_layout.addWidget(button_hor_sub_widget) self._setting_dlg.setVisible(True) self._setting_dlg.finished.connect(self._destroy_setting_dlg) self.is_setting_dlg_live = True pass
def _create_add_rocon_master_dialog(self): # dialog connect_dlg = QDialog(self._widget_main) connect_dlg.setWindowTitle("Add Ros Master") connect_dlg.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) connect_dlg.setMinimumSize(350, 0) # dlg_rect = self._connect_dlg.geometry() # dialog layout ver_layout = QVBoxLayout(connect_dlg) ver_layout.setContentsMargins(9, 9, 9, 9) # param layout text_grid_sub_widget = QWidget() text_grid_layout = QGridLayout(text_grid_sub_widget) text_grid_layout.setColumnStretch(1, 0) text_grid_layout.setRowStretch(2, 0) # param 1 title_widget1 = QLabel("MASTER_URI: ") context_widget1 = QTextEdit() context_widget1.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) context_widget1.setMinimumSize(0, 30) context_widget1.append(self.master_uri) # param 2 title_widget2 = QLabel("HOST_NAME: ") context_widget2 = QTextEdit() context_widget2.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) context_widget2.setMinimumSize(0, 30) context_widget2.append(self.host_name) # add param text_grid_layout.addWidget(title_widget1) text_grid_layout.addWidget(context_widget1) text_grid_layout.addWidget(title_widget2) text_grid_layout.addWidget(context_widget2) # add param layout ver_layout.addWidget(text_grid_sub_widget) # button layout button_hor_sub_widget = QWidget() button_hor_layout = QHBoxLayout(button_hor_sub_widget) uri_text_widget = context_widget1 host_name_text_widget = context_widget2 # button btn_call = QPushButton("Add") btn_cancel = QPushButton("Cancel") btn_call.clicked.connect(lambda: connect_dlg.done(0)) btn_call.clicked.connect(lambda: self._add_rocon_master( uri_text_widget, host_name_text_widget)) btn_cancel.clicked.connect(lambda: connect_dlg.done(0)) # add button button_hor_layout.addWidget(btn_call) button_hor_layout.addWidget(btn_cancel) # add button layout ver_layout.addWidget(button_hor_sub_widget) return connect_dlg
class RoomDialogPlugin(Plugin): def __init__(self, context): super(RoomDialogPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('RoomDialogPlugin') font_size = rospy.get_param("~font_size", 30) # Create QWidget self._widget = QWidget() self._widget.setFont(QFont("Times", font_size, QFont.Bold)) self._layout = QVBoxLayout(self._widget) self._text_browser = QTextBrowser(self._widget) self._layout.addWidget(self._text_browser) self._button_layout = QGridLayout() self._layout.addLayout(self._button_layout) # rospy.loginfo("Hello world") # Add combobox self._cb_layout = QHBoxLayout() self._cb = QComboBox() self._layout.addLayout(self._cb_layout) #layout = QVBoxLayout(self._widget) #layout.addWidget(self._button) self._widget.setObjectName('RoomDialogPluginUI') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) # Setup service provider self.service = rospy.Service('room_dialog', RoomDialog, self.service_callback) self.response_ready = False self.response = None self.buttons = [] self.text_label = None self.text_input = None # Add combo options self.connect(self._widget, SIGNAL("update"), self.update) self.connect(self._widget, SIGNAL("timeout"), self.timeout) def shutdown_plugin(self): self.service.shutdown() def service_callback(self, req): self.response_ready = False self.request = req self._widget.emit(SIGNAL("update")) # Start timer against wall clock here instead of the ros clock. start_time = time.time() while not self.response_ready: if self.request != req: # The request got preempted by a new request. return RoomDialogResponse(RoomDialogRequest.PREEMPTED, "") if req.timeout != RoomDialogRequest.NO_TIMEOUT: current_time = time.time() if current_time - start_time > req.timeout: self._widget.emit(SIGNAL("timeout")) return RoomDialogResponse(RoomDialogRequest.TIMED_OUT, "") time.sleep(0.2) return self.response def update(self): self.clean() req = self.request self._text_browser.setText(req.message) if req.type == RoomDialogRequest.DISPLAY: # All done, nothing more too see here. self.response = RoomDialogResponse(RoomDialogRequest.NO_RESPONSE, "") self.response_ready = True elif req.type == RoomDialogRequest.CHOICE_QUESTION: for index, options in enumerate(req.options): button = QPushButton(options, self._widget) button.clicked.connect(partial(self.handle_button, index)) row = index / 3 col = index % 3 self._button_layout.addWidget(button, row, col) self.buttons.append(button) elif req.type == RoomDialogRequest.TEXT_QUESTION: self.text_label = QLabel("Enter here: ", self._widget) self._button_layout.addWidget(self.text_label, 0, 0) self.text_input = QLineEdit(self._widget) self.text_input.editingFinished.connect(self.handle_text) self._button_layout.addWidget(self.text_input, 0, 1) # add handling of combobox elif req.type == RoomDialogRequest.COMBOBOX_QUESTION: # self.clean() rospy.loginfo("Combobox selected") #self._cb.duplicatesEnabled = False if self._cb.count() == 0: for index, options in enumerate(req.options): self._cb.addItem(options) rospy.loginfo(options) #self.buttons.append(options) # NOTE COULD INTRODUCE BUG self._cb.currentIndexChanged.connect(self.handle_cb) self._cb_layout.addWidget(self._cb) def timeout(self): self._text_browser.setText("Oh no! The request timed out.") self.clean() def clean(self): while self._button_layout.count(): item = self._button_layout.takeAt(0) item.widget().deleteLater() # while self._cb_layout.count(): # item = self._cb_layout.takeAt(0) # item.widget().deleteLater() self.buttons = [] self.text_input = None self.text_label = None def handle_button(self, index): self.response = RoomDialogResponse(index, "") self.clean() self.response_ready = True def handle_text(self): self.response = RoomDialogResponse(RoomDialogRequest.TEXT_RESPONSE, self.text_input.text()) self.clean() self.response_ready = True def handle_cb(self, index): # This will be the sign format seen around building ex: 3.404 rospy.loginfo("handling cb") roomHuman = self._cb.currentText() # modify string into robot format ex: d3_404 splitHuman = roomHuman.split('.', 1) roomRobot = 'd' + splitHuman[0] + '_' + splitHuman[1] roomRobot = str(roomRobot) self.response = RoomDialogResponse(RoomDialogRequest.CB_RESPONSE, roomRobot) self.clean() self.response_ready = True 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