def _update_client_tab(self): print('[conductor graph]: _update_client_tab') self.pre_selected_client_name = self.cur_selected_client_name self._widget.tabWidget.clear() for k in self._graph.concert_clients.values(): # Only pull in information from connected or connectable clients if k.state not in [ concert_msgs.ConcertClientState.AVAILABLE, concert_msgs.ConcertClientState.MISSING, concert_msgs.ConcertClientState.UNINVITED ]: continue main_widget = QWidget() ver_layout = QVBoxLayout(main_widget) ver_layout.setContentsMargins(9, 9, 9, 9) ver_layout.setSizeConstraint(ver_layout.SetDefaultConstraint) #button layout sub_widget = QWidget() sub_widget.setAccessibleName('sub_widget') ver_layout.addWidget(sub_widget) #client information layout context_label = QLabel() context_label.setText("Client information") ver_layout.addWidget(context_label) app_context_widget = QPlainTextEdit() app_context_widget.setObjectName(k.concert_alias + '_' + 'app_context_widget') app_context_widget.setAccessibleName('app_context_widget') app_context_widget.appendHtml(k.get_rapp_context()) app_context_widget.setReadOnly(True) cursor = app_context_widget.textCursor() cursor.movePosition(QTextCursor.Start, QTextCursor.MoveAnchor, 0) app_context_widget.setTextCursor(cursor) ver_layout.addWidget(app_context_widget) # new icon path = "" if k.is_new: # This only changes when the concert client changes topic publishes anew path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../resources/images/new.gif") #add tab self._widget.tabWidget.addTab(main_widget, QIcon(path), k.concert_alias) #set previous selected tab for k in range(self._widget.tabWidget.count()): tab_text = self._widget.tabWidget.tabText(k) if tab_text == self.pre_selected_client_name: self._widget.tabWidget.setCurrentIndex(k)
def __init__(self, host, masteruri=None, parent=None): PackageDialog.__init__(self, parent) self.host = host self.setWindowTitle('Run') ns_name_label = QLabel("NS/Name:", self.content) self.ns_field = QComboBox(self.content) self.ns_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.ns_field.setEditable(True) ns_history = nm.history().cachedParamValues('run_dialog/NS') ns_history.insert(0, '/') self.ns_field.addItems(ns_history) self.name_field = QLineEdit(self.content) self.name_field.setEnabled(False) horizontalLayout = QHBoxLayout() horizontalLayout.addWidget(self.ns_field) horizontalLayout.addWidget(self.name_field) self.contentLayout.addRow(ns_name_label, horizontalLayout) args_label = QLabel("Args:", self.content) self.args_field = QComboBox(self.content) self.args_field.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) self.args_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.args_field.setEditable(True) self.contentLayout.addRow(args_label, self.args_field) args_history = nm.history().cachedParamValues('run_dialog/Args') args_history.insert(0, '') self.args_field.addItems(args_history) host_label = QLabel("Host:", self.content) self.host_field = QComboBox(self.content) # self.host_field.setSizeAdjustPolicy(QComboBox.AdjustToContents) self.host_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.host_field.setEditable(True) host_label.setBuddy(self.host_field) self.contentLayout.addRow(host_label, self.host_field) self.host_history = host_history = nm.history().cachedParamValues('/Host') if self.host in host_history: host_history.remove(self.host) host_history.insert(0, self.host) self.host_field.addItems(host_history) master_label = QLabel("ROS Master URI:", self.content) self.master_field = QComboBox(self.content) self.master_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.master_field.setEditable(True) master_label.setBuddy(self.host_field) self.contentLayout.addRow(master_label, self.master_field) self.master_history = master_history = nm.history().cachedParamValues('/Optional Parameter/ROS Master URI') self.masteruri = "ROS_MASTER_URI" if masteruri is None else masteruri if self.masteruri in master_history: master_history.remove(self.masteruri) master_history.insert(0, self.masteruri) self.master_field.addItems(master_history) # self.package_field.setFocus(QtCore.Qt.TabFocusReason) if hasattr(self.package_field, "textChanged"): # qt compatibility self.package_field.textChanged.connect(self.on_package_selected) else: self.package_field.editTextChanged.connect(self.on_package_selected) self.binary_field.activated[str].connect(self.on_binary_selected)
def _create_buttons(self): # create the buttons line self.buttons = QWidget(self) self.horizontalLayout = QHBoxLayout(self.buttons) self.horizontalLayout.setContentsMargins(4, 0, 4, 0) self.horizontalLayout.setObjectName("horizontalLayout") # add the search button self.searchButton = QPushButton(self) self.searchButton.setObjectName("searchButton") # self.searchButton.clicked.connect(self.on_shortcut_find) self.searchButton.toggled.connect(self.on_toggled_find) self.searchButton.setText(self._translate("&Find")) self.searchButton.setToolTip('Open a search dialog (Ctrl+F)') self.searchButton.setFlat(True) self.searchButton.setCheckable(True) self.horizontalLayout.addWidget(self.searchButton) # add the replace button self.replaceButton = QPushButton(self) self.replaceButton.setObjectName("replaceButton") # self.replaceButton.clicked.connect(self.on_shortcut_replace) self.replaceButton.toggled.connect(self.on_toggled_replace) self.replaceButton.setText(self._translate("&Replace")) self.replaceButton.setToolTip('Open a search&replace dialog (Ctrl+R)') self.replaceButton.setFlat(True) self.replaceButton.setCheckable(True) self.horizontalLayout.addWidget(self.replaceButton) # add the goto button self.gotoButton = QPushButton(self) self.gotoButton.setObjectName("gotoButton") self.gotoButton.clicked.connect(self.on_shortcut_goto) self.gotoButton.setText(self._translate("&Goto line")) self.gotoButton.setShortcut("Ctrl+G") self.gotoButton.setToolTip('Open a goto dialog (Ctrl+G)') self.gotoButton.setFlat(True) self.horizontalLayout.addWidget(self.gotoButton) # add a tag button self.tagButton = self._create_tag_button(self) self.horizontalLayout.addWidget(self.tagButton) # add spacer spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) # add line number label self.pos_label = QLabel() self.horizontalLayout.addWidget(self.pos_label) # add spacer spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) # add save button self.saveButton = QPushButton(self) self.saveButton.setObjectName("saveButton") self.saveButton.clicked.connect(self.on_saveButton_clicked) self.saveButton.setText(self._translate("&Save")) self.saveButton.setShortcut("Ctrl+S") self.saveButton.setToolTip('Save the changes to the file (Ctrl+S)') self.saveButton.setFlat(True) self.horizontalLayout.addWidget(self.saveButton) return self.buttons
def clearLayoutAndFixHeight(layout): # Clear all subfunction buttons. while layout.count(): item = layout.takeAt(0) if item.widget() is not None: item.widget().deleteLater() height_label = QLabel() height_label.setFixedHeight(30) layout.addWidget(height_label)
def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle('Select Binary') self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.content = QWidget() self.contentLayout = QFormLayout(self.content) self.contentLayout.setVerticalSpacing(0) self.verticalLayout.addWidget(self.content) self.packages = None package_label = QLabel("Package:", self.content) self.package_field = QComboBox(self.content) self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically) self.package_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.package_field.setEditable(True) self.contentLayout.addRow(package_label, self.package_field) binary_label = QLabel("Binary:", self.content) self.binary_field = QComboBox(self.content) # self.binary_field.setSizeAdjustPolicy(QComboBox.AdjustToContents) self.binary_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.binary_field.setEditable(True) self.contentLayout.addRow(binary_label, self.binary_field) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) self.package_field.setFocus(Qt.TabFocusReason) self.package = '' self.binary = '' if self.packages is None: self.package_field.addItems(['packages searching...']) self.package_field.setCurrentIndex(0) self._fill_packages_thread = PackagesThread() self._fill_packages_thread.packages.connect(self._fill_packages) self._fill_packages_thread.start() self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) QMetaObject.connectSlotsByName(self) self.package_field.activated[str].connect(self.on_package_selected) if hasattr(self.package_field, "textChanged"): # qt compatibility self.package_field.textChanged.connect(self.on_package_selected) self.binary_field.textChanged.connect(self.on_binary_selected) else: self.package_field.editTextChanged.connect(self.on_package_selected) self.binary_field.editTextChanged.connect(self.on_binary_selected)
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 __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 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, options, title='Exclusive Options', selected_index=None): super(ExclusiveOptionGroup, self).__init__() self.setTitle(title) self.setLayout(QVBoxLayout()) self._button_group = QButtonGroup() self._button_group.setExclusive(True) self._options = options button_id = 0 for option in self._options: button_id += 1 radio_button = QRadioButton( option.get('title', 'option %d' % button_id)) radio_button.setEnabled(option.get('enabled', True)) radio_button.setChecked( option.get('selected', False) or (button_id - 1) == selected_index) radio_button.setToolTip(option.get('tooltip', '')) widget = QWidget() widget.setLayout(QVBoxLayout()) widget.layout().addWidget(radio_button) if 'description' in option: widget.layout().addWidget(QLabel(option['description'])) self._button_group.addButton(radio_button, button_id) self.layout().addWidget(widget)
def __init__(self, options, title='Checkboxes', selected_indexes=[], parent=None): super(CheckBoxGroup, self).__init__() self.setTitle(title) self.setLayout(QVBoxLayout()) self._button_group = QButtonGroup() self._button_group.setExclusive(False) self._options = options if parent == None: parent = self for (button_id, option) in enumerate(self._options): checkbox = QCheckBox(option.get('title', 'option %d' % button_id)) checkbox.setEnabled(option.get('enabled', True)) checkbox.setChecked(button_id in selected_indexes) checkbox.setToolTip(option.get('tooltip', '')) self._button_group.addButton(checkbox, button_id) parent.layout().addWidget(checkbox) if 'description' in option: parent.layout().addWidget(QLabel(option['description']))
def _set_parameter_layout(self): params = self.admin_app_interface.get_srv_parameters( self.current_service['parameters_detail']) is_enabled = self.current_service['enabled'] if self.params_layout_items: for item in self.params_layout_items: self.params_layout.removeWidget(item[0]) self.params_layout.removeWidget(item[1]) item[0].setParent(None) item[1].setParent(None) self.params_layout_items = [] if params: self.params_layout.setColumnStretch(1, 0) self.params_layout.setRowStretch(2, 0) for param in params.keys(): label = QLabel(param) self.params_layout.addWidget(label) value = QTextEdit(str(params[param])) value.setMaximumHeight(30) self.params_layout.addWidget(value) self.params_layout_items.append((label, value)) self._set_enable_params_layout(not is_enabled)
def __init__(self, context): super(EusGUI, self).__init__(context) # Give QObjects reasonable names self.setObjectName('EusGUI') self.msg = None # Create a container widget and give it a layout self._toolbar = QToolBar() self._toolbar.addWidget(QLabel('EusGUI')) self._container = QWidget() self._layout = QVBoxLayout() self._container.setLayout(self._layout) self._layout.addWidget(self._toolbar) self._prev_button = QPushButton('PREV') self._prev_button.clicked.connect(self._prev_cb) self._layout.addWidget(self._prev_button) self._refresh_button = QPushButton('DO IT AGAIN') self._refresh_button.clicked.connect(self._refresh_cb) self._layout.addWidget(self._refresh_button) self._next_button = QPushButton('NEXT') self._next_button.clicked.connect(self._next_cb) self._layout.addWidget(self._next_button) context.add_widget(self._container)
def __init__(self, context): super(LevelSelectorPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('LevelSelectorPlugin') # Create QWidget self._widget = QWidget() # self._widget.setFont(QFont("Times", 15, QFont.Bold)) self._button_layout = QVBoxLayout(self._widget) self.buttons = [] self.text_label = QLabel("Waiting for MultiLevelMapData...", self._widget) self._button_layout.addWidget(self.text_label) self._widget.setObjectName('LevelSelectorPluginUI') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) self.connect(self._widget, SIGNAL("update_buttons"), self.update_buttons) self.connect(self._widget, SIGNAL("update_button_status"), self.update_button_status) # Subcribe to the multi level map data to get information about all the maps. self.multimap_subscriber = rospy.Subscriber("map_metadata", MultiLevelMapData, self.process_multimap) self.levels = [] self.current_level = None # Subscribe to the current level we are on. self.status_subscriber = None # Create a service proxy to change the current level. self.level_selector_proxy = rospy.ServiceProxy("level_mux/change_current_level", ChangeCurrentLevel) self.level_selector_proxy.wait_for_service()
def __init__(self, options, title='Exclusive Options', selected_index=None, parent=None): super(ExclusiveOptionGroup, self).__init__() self.setTitle(title) self.setLayout(QVBoxLayout()) self._button_group = QButtonGroup() self._button_group.setExclusive(True) self._options = options if parent == None: parent = self for (button_id, option) in enumerate(self._options): radio_button = QRadioButton( option.get('title', 'option %d' % button_id)) radio_button.setEnabled(option.get('enabled', True)) radio_button.setChecked( option.get('selected', False) or button_id == selected_index) radio_button.setToolTip(option.get('tooltip', '')) self._button_group.addButton(radio_button, button_id) parent.layout().addWidget(radio_button) if 'description' in option: parent.layout().addWidget(QLabel(option['description']))
def __init__(self, motion_publisher, robot_config): super(MotionEditorWidget, self).__init__() self.robot_config = robot_config self._motion_publisher = motion_publisher self._motion_data = MotionData(robot_config) self._filter_pattern = '' self._playback_marker = None self._playback_timer = None ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'motion_editor.ui') loadUi(ui_file, self) self.list_widgets = {} for group_type in robot_config.group_types(): list_widget = QListWidget() list_widget.setSortingEnabled(True) list_widget.setDragDropMode(QAbstractItemView.DragOnly) list_widget.setContextMenuPolicy(Qt.CustomContextMenu) list_widget.customContextMenuRequested.connect( lambda pos, _group_type=group_type: self. positions_list_context_menu(_group_type, pos)) list_widget.itemChanged.connect(self.on_list_item_changed) self.position_lists_layout.addWidget(list_widget) self.list_widgets[group_type] = list_widget self._timeline_widget = TimelineWidget() for track_name in self.robot_config.sorted_groups(): track_type = self.robot_config.groups[track_name].group_type track = self._timeline_widget.add_track(track_name, track_type) list_widget = self.list_widgets[track_type] palette = list_widget.palette() palette.setColor(QPalette.Base, track._colors['track']) list_widget.setPalette(palette) self.timeline_group.layout().addWidget(self._timeline_widget) for group_type in robot_config.group_types(): label = QLabel(group_type) label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.group_label_layout.addWidget(label) self.update_motion_name_combo() self.stop_motion_button.pressed.connect(self.on_motion_stop_pressed)
def __init__(self, motion_publisher, robot_config): super(MotionEditorWidget, self).__init__() self.robot_config = robot_config self._motion_publisher = motion_publisher self._motion_data = MotionData(robot_config) self._filter_pattern = '' self._playback_marker = None self._playback_timer = None ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'motion_editor.ui') loadUi(ui_file, self) self.list_widgets = {} for group_type in robot_config.group_types(): list_widget = QListWidget() list_widget.setSortingEnabled(True) list_widget.setDragDropMode(QAbstractItemView.DragOnly) list_widget.setContextMenuPolicy(Qt.CustomContextMenu) list_widget.customContextMenuRequested.connect( lambda pos, _group_type=group_type: self.positions_list_context_menu(_group_type, pos) ) list_widget.itemChanged.connect(self.on_list_item_changed) self.position_lists_layout.addWidget(list_widget) self.list_widgets[group_type] = list_widget self._timeline_widget = TimelineWidget() for track_name in self.robot_config.sorted_groups(): track_type = self.robot_config.groups[track_name].group_type track = self._timeline_widget.add_track(track_name, track_type) list_widget = self.list_widgets[track_type] palette = list_widget.palette() palette.setColor(QPalette.Base, track._colors['track']) list_widget.setPalette(palette) self.timeline_group.layout().addWidget(self._timeline_widget) for group_type in robot_config.group_types(): label = QLabel(group_type) label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) self.group_label_layout.addWidget(label) self.update_motion_name_combo() self.stop_motion_button.pressed.connect(self.on_motion_stop_pressed)
def __init__(self, masteruri, cfg, ns, nodes, parent=None): QFrame.__init__(self, parent) self._masteruri = masteruri self._nodes = {cfg: {ns: nodes}} frame_layout = QVBoxLayout(self) frame_layout.setContentsMargins(0, 0, 0, 0) # create frame for warning label self.warning_frame = warning_frame = QFrame(self) warning_layout = QHBoxLayout(warning_frame) warning_layout.setContentsMargins(0, 0, 0, 0) warning_layout.addItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.warning_label = QLabel() icon = nm.settings().icon('crystal_clear_warning.png') self.warning_label.setPixmap(icon.pixmap(QSize(40, 40))) self.warning_label.setToolTip( 'Multiple configuration for same node found!\nA first one will be selected for the start a node!' ) warning_layout.addWidget(self.warning_label) warning_layout.addItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) frame_layout.addItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) frame_layout.addWidget(warning_frame) # create frame for start/stop buttons buttons_frame = QFrame() buttons_layout = QHBoxLayout(buttons_frame) buttons_layout.setContentsMargins(0, 0, 0, 0) buttons_layout.addItem(QSpacerItem(20, 20)) self.on_button = QPushButton() self.on_button.setFlat(False) self.on_button.setText("On") self.on_button.clicked.connect(self.on_on_clicked) buttons_layout.addWidget(self.on_button) self.off_button = QPushButton() self.off_button.setFlat(True) self.off_button.setText("Off") self.off_button.clicked.connect(self.on_off_clicked) buttons_layout.addWidget(self.off_button) buttons_layout.addItem(QSpacerItem(20, 20)) frame_layout.addWidget(buttons_frame) frame_layout.addItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.warning_frame.setVisible(False)
def add_info_no_screen(self, nodename): if self.questionid == self.TYPE_NOSCREEN: self.data.data.append(nodename) self.frameui.scrollAreaLayout.addWidget(QLabel(nodename)) else: self._queue.add(self.TYPE_NOSCREEN, '', MessageData([nodename])) if self.questionid == self.TYPE_INVALID: self._new_request = self._read_next_item() self._frameui_4_request(self._new_request)
def __init__(self): super(StringLabelWidget, self).__init__() self.lock = Lock() vbox = QtGui.QVBoxLayout(self) self.label = QLabel() self.label.setAlignment(Qt.AlignLeft) self.label.setSizePolicy( QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)) font = QFont("Helvetica", 14) self.label.setFont(font) self.label.setWordWrap(True) vbox.addWidget(self.label) self.string_sub = None self._string_topics = [] self._update_topic_timer = QTimer(self) self._update_topic_timer.timeout.connect(self.updateTopics) self._update_topic_timer.start(1) self._active_topic = None self._dialog = ComboBoxDialog()
def _load_parameter(self,param_index,param_name, param_type,param_value, param_min, param_max, param_desc): x_check = 160 x ,y ,w ,h = 4,4 + 40 * param_index,150,20 label = QLabel(param_name,self.parameters) label.setGeometry(x,y,w,h) label.setToolTip(param_desc) label.show() if param_type == 'Boolean': checkbox = QCheckBox('',self.parameters) checkbox.setGeometry(x_check,y,w,h) checkbox.setChecked(param_value == '1') checkbox.setToolTip(param_desc) checkbox.stateChanged.connect(partial(self._handle_bool_param_changed,param_name)) checkbox.show() elif param_type == 'Integer': if len(param_min) > 0 and len(param_max) > 0 and int(param_max) < 5: slider = QSlider(Qt.Horizontal,self.parameters) slider.setMinimum(int(param_min)) slider.setMaximum(int(param_max)) slider.setValue(int(param_value)) slider.setTickPosition(QSlider.TicksBelow) slider.setGeometry(x_check,y,w,h) slider.setToolTip(param_desc) slider.setTickInterval(1) slider.setSingleStep(1) slider.setPageStep(1) slider.valueChanged.connect(partial(self._handle_param_changed,param_name)) slider.show() else: spin = QSpinBox(self.parameters) if len(param_min) > 0: spin.setMinimum(int(param_min)) if len(param_max) > 0: spin.setMaximum(int(param_max)) spin.setValue(int(param_value)) spin.setToolTip(param_desc) spin.setGeometry(x_check,y,w,h) spin.valueChanged.connect(partial(self._handle_param_changed,param_name)) spin.show() elif param_type == 'Double': spin = QDoubleSpinBox(self.parameters) if len(param_min) > 0: spin.setMinimum(float(param_min)) if len(param_max) > 0: spin.setMaximum(float(param_max)) spin.setValue(float(param_value)) spin.valueChanged.connect(partial(self._handle_param_changed,param_name)) spin.setGeometry(x_check,y,w,h) spin.show() elif param_type == 'String': lineEdit = QLineEdit(self.parameters) lineEdit.setText(param_value) lineEdit.setToolTip(param_desc) lineEdit.setGeometry(x_check,y,w,h) lineEdit.textChanged.connect(partial(self._handle_param_changed,param_name)) lineEdit.show() self.parameters.update()
def _create_replace_frame(self): # create frame with replace row self.rplc_frame = rplc_frame = QFrame(self) rplc_hbox_layout = QHBoxLayout(rplc_frame) rplc_hbox_layout.setContentsMargins(0, 0, 0, 0) rplc_hbox_layout.setSpacing(1) self.replace_field = EnchancedLineEdit(rplc_frame) self.replace_field.setPlaceholderText('replace text') self.replace_field.returnPressed.connect(self.on_replace) rplc_hbox_layout.addWidget(self.replace_field) self.replace_result_label = QLabel(rplc_frame) self.replace_result_label.setText(' ') rplc_hbox_layout.addWidget(self.replace_result_label) self.replace_button = replace_button = QPushButton("> &Replace >") replace_button.setFixedWidth(90) replace_button.clicked.connect(self.on_replace_click) rplc_hbox_layout.addWidget(replace_button) rplc_frame.setVisible(False) return rplc_frame
class PingGUI(Plugin): def __init__(self, context): super(PingGUI, self).__init__(context) # Give QObjects reasonable names self.setObjectName('PingGUI') self.msg = None # Create a container widget and give it a layout self._container = QWidget() self._layout = QVBoxLayout() self._container.setLayout(self._layout) self._label = QLabel("xx ms latency") p = self._label.palette() p.setColor(self._label.backgroundRole(), Qt.red) self._label.setPalette(p) self._layout.addWidget(self._label) self.set_bg_color(100, 100, 100) rospy.Subscriber("/ping/delay", Float64, self.ping_cb) context.add_widget(self._container) self._update_plot_timer = QTimer(self) self._update_plot_timer.timeout.connect(self.update_gui) self._update_plot_timer.start(1) def update_gui(self): if not self.msg: return msg = self.msg # msec # 100 -> green, 1000 -> red # normalize within 1000 ~ 100 orig_latency = msg.data msg_data = orig_latency if msg.data > 1000: msg_data = 1000 elif msg.data < 100: msg_data = 100 ratio = (msg_data - 100) / (1000 - 100) color_r = ratio * 255.0 color_g = (1 - ratio) * 255.0 # devnull = open(os.devnull, "w") # with RedirectStdStreams(stdout=devnull, stderr=devnull): self.set_bg_color(color_r, color_g, 0) self._label.setText("%d ms latency" % (orig_latency)) def set_bg_color(self, r, g, b): self._label.setStyleSheet("QLabel { display: block; background-color: rgba(%d, %d, %d, 255); text-align: center; font-size: 30px;}" % (r, g, b)) def ping_cb(self, msg): self.msg = msg def shutdown_plugin(self): pass def save_settings(self, plugin_settings, instance_settings): pass def restore_settings(self, plugin_settings, instance_settings): pass
def __init__(self, default_mcast_group, default_port, networks_count, parent=None): ''' Creates an input dialog. @param default_port: the default discovery port @type default_port: C{int} @param networks_count: the count of discovering ports @type networks_count: C{int} ''' QDialog.__init__(self, parent=parent) threading.Thread.__init__(self) self.default_port = default_port self.setObjectName('NetworkDiscoveryDialog') self.setAttribute(Qt.WA_DeleteOnClose, True) self.setWindowFlags(Qt.Window) self.setWindowTitle('Network Discovery') self.resize(728, 512) self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) self.display = QTextBrowser(self) self.display.setReadOnly(True) self.verticalLayout.addWidget(self.display) self.display_clear_signal.connect(self.display.clear) self.display_append_signal.connect(self.display.append) self.display.anchorClicked.connect(self.on_anchorClicked) self.status_label = QLabel('0 messages', self) self.verticalLayout.addWidget(self.status_label) self.status_text_signal.connect(self.status_label.setText) self._msg_counts = dict() self._networks_count = networks_count self._running = True self._received_msgs = 0 self._discovered = dict() self._hosts = dict() # resolution for hostname and address self.mutex = threading.RLock() self.sockets = [] with self.mutex: try: for p in range(networks_count): msock = DiscoverSocket(default_port + p, default_mcast_group) self.sockets.append(msock) msock.settimeout(self.TIMEOUT) except Exception as e: self.display.setText(utf8(e)) self.setDaemon(True) self.start()
def __init__(self, context): super(PingGUI, self).__init__(context) # Give QObjects reasonable names self.setObjectName('PingGUI') self.msg = None # Create a container widget and give it a layout self._container = QWidget() self._layout = QVBoxLayout() self._container.setLayout(self._layout) self._label = QLabel("xx ms latency") p = self._label.palette() p.setColor(self._label.backgroundRole(), Qt.red) self._label.setPalette(p) self._layout.addWidget(self._label) self.set_bg_color(100, 100, 100) rospy.Subscriber("/ping/delay", Float64, self.ping_cb) context.add_widget(self._container) self._update_plot_timer = QTimer(self) self._update_plot_timer.timeout.connect(self.update_gui) self._update_plot_timer.start(1)
def __init__(self, parent, fileName, top_widget_layout): self.controllers = [] self.parent = parent self.loadFile(fileName) print "Initialize controllers..." for controller in self.controllers: frame = QFrame() frame.setFrameShape(QFrame.StyledPanel); frame.setFrameShadow(QFrame.Raised); vbox = QVBoxLayout() label = QLabel() label.setText(controller.label) vbox.addWidget(label); print controller.name for joint in controller.joints: label = QLabel() label.setText(joint.name) vbox.addWidget(label); #Add input for setting the biases widget = QWidget() hbox = QHBoxLayout() hbox.addWidget(joint.sensor_bias_spinbox) hbox.addWidget(joint.control_bias_spinbox) hbox.addWidget(joint.gearing_bias_spinbox) widget.setLayout(hbox) vbox.addWidget(widget) label = QLabel() label.setText(" Sensor Control Gearing") vbox.addWidget(label); vbox.addStretch() frame.setLayout(vbox) top_widget_layout.addWidget(frame) print "Done loading controllers"
def __init__(self): super(CalibrationMovementsGUI, self).__init__() move_group_name = rospy.get_param('~move_group', 'manipulator') self.angle_delta = math.radians( rospy.get_param('~rotation_delta_degrees', 25)) self.translation_delta = rospy.get_param('~translation_delta_meters', 0.1) max_velocity_scaling = rospy.get_param('~max_velocity_scaling', 0.5) max_acceleration_scaling = rospy.get_param('~max_acceleration_scaling', 0.5) self.local_mover = CalibrationMovements(move_group_name, max_velocity_scaling, max_acceleration_scaling) self.current_pose = -1 self.current_plan = None self.state = CalibrationMovementsGUI.NOT_INITED_YET self.layout = QVBoxLayout() self.labels_layout = QHBoxLayout() self.buttons_layout = QHBoxLayout() self.progress_bar = QProgressBar() self.pose_number_lbl = QLabel('0/8') self.bad_plan_lbl = QLabel('No plan yet') self.guide_lbl = QLabel('Hello') self.guide_lbl.setWordWrap(True) self.check_start_pose_btn = QPushButton('Check starting pose') self.check_start_pose_btn.clicked.connect( self.handle_check_current_state) self.next_pose_btn = QPushButton('Next Pose') self.next_pose_btn.clicked.connect(self.handle_next_pose) self.plan_btn = QPushButton('Plan') self.plan_btn.clicked.connect(self.handle_plan) self.execute_btn = QPushButton('Execute') self.execute_btn.clicked.connect(self.handle_execute) self.labels_layout.addWidget(self.pose_number_lbl) self.labels_layout.addWidget(self.bad_plan_lbl) self.buttons_layout.addWidget(self.check_start_pose_btn) self.buttons_layout.addWidget(self.next_pose_btn) self.buttons_layout.addWidget(self.plan_btn) self.buttons_layout.addWidget(self.execute_btn) self.layout.addWidget(self.progress_bar) self.layout.addLayout(self.labels_layout) self.layout.addWidget(self.guide_lbl) self.layout.addLayout(self.buttons_layout) self.setLayout(self.layout) self.plan_btn.setEnabled(False) self.execute_btn.setEnabled(False) self.setWindowTitle('Local Mover') self.show()
def __init__(self, context): super(LevelSelectorPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('LevelSelectorPlugin') # Create QWidget self._widget = QWidget() # self._widget.setFont(QFont("Times", 15, QFont.Bold)) self._button_layout = QVBoxLayout(self._widget) self.buttons = [] self.text_label = QLabel("Waiting for MultiLevelMapData...", self._widget) self._button_layout.addWidget(self.text_label) self._widget.setObjectName('LevelSelectorPluginUI') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) self.connect(self._widget, SIGNAL("update_buttons"), self.update_buttons) self.connect(self._widget, SIGNAL("update_button_status"), self.update_button_status) # Subcribe to the multi level map data to get information about all the maps. self.multimap_subscriber = rospy.Subscriber("map_metadata", MultiLevelMapData, self.process_multimap) self.levels = [] self.current_level = None # Subscribe to the current level we are on. self.status_subscriber = None # Create a service proxy to change the current level. self.level_selector_proxy = rospy.ServiceProxy( "level_mux/change_current_level", ChangeCurrentLevel) self.level_selector_proxy.wait_for_service()
def __init__(self, context): super(ImageSnapShotGUI, self).__init__(context) # Give QObjects reasonable names self.setObjectName('ImageSnapShotGUI') # 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()) self._toolbar = QToolBar() self._toolbar.addWidget(QLabel('ImageSnapShot')) # Create a container widget and give it a layout self._container = QWidget() self._layout = QVBoxLayout() self._container.setLayout(self._layout) self._layout.addWidget(self._toolbar) # Add a button for .... self._go_button = QPushButton('Head') self._go_button.clicked.connect(self._head) self._layout.addWidget(self._go_button) self._clear_button = QPushButton('Larm') self._clear_button.clicked.connect(self._larm) self._layout.addWidget(self._clear_button) self._clear_button = QPushButton('Rarm') self._clear_button.clicked.connect(self._rarm) self._layout.addWidget(self._clear_button) self._clear_button = QPushButton('L FishEye') self._clear_button.clicked.connect(self._lfisheye) self._layout.addWidget(self._clear_button) self._clear_button = QPushButton('R FishEye') self._clear_button.clicked.connect(self._rfisheye) self._layout.addWidget(self._clear_button) # self._step_run_button.setStyleSheet('QPushButton {color: black}') context.add_widget(self._container) self._head_pub = rospy.Publisher('/head_snap/snapshot', std_msgs.msg.Empty) self._lhand_pub = rospy.Publisher('/lhand_snap/snapshot', std_msgs.msg.Empty) self._rhand_pub = rospy.Publisher('/rhand_snap/snapshot', std_msgs.msg.Empty) self._lfisheye_pub = rospy.Publisher('/lfisheye_snap/snapshot', std_msgs.msg.Empty) self._rfisheye_pub = rospy.Publisher('/rfisheye_snap/snapshot', std_msgs.msg.Empty)
def startAreaEdit(self, edit_type): if self.editing_properties: self.endPropertyEdit() self.editing_area = True if edit_type == LocationFunction.ADD_LOCATION_AREA: self.edit_existing_location = None # else edit_existing_location was set to the correct location by startPropertyEdit() # Make sure all active selections have been cleared. self.clearAreaSelection() # If we're going to edit an existing area, stop drawing it and copy it to the active selection. if self.edit_existing_location is not None: self.draw_location[self.edit_existing_location] = False self.current_selection = QPolygon( self.locations[self.edit_existing_location]) self.edit_existing_location = self.edit_existing_location # Setup the buttons in the configuration toolbar, and disable the original buttons to edit an area. clearLayoutAndFixHeight(self.configuration_layout) for button_text in ["Done", "Cancel"]: button = QPushButton(button_text, self.widget) button.clicked[bool].connect(partial(self.endAreaEdit, button_text)) self.configuration_layout.addWidget(button) self.current_selection_label = QLabel(self.widget) self.configuration_layout.addWidget(self.current_selection_label) self.configuration_layout.addStretch(1) self.edit_area_button[LocationFunction.ADD_LOCATION_AREA].setEnabled( False) self.edit_area_button[LocationFunction.EDIT_EXISTING_AREA].setEnabled( False) self.updateOverlay()
def __init__(self, main, fileName, main_hbox): self.main = main self.chain = [] self.poses = [] self.chain_name = "" frame = QFrame() frame.setFrameShape(QFrame.StyledPanel); frame.setFrameShadow(QFrame.Raised); vbox = QVBoxLayout() label = QLabel() vbox.addWidget(label); self.load_file(fileName, vbox) self.trajectoryPublisher = rospy.Publisher('/trajectory_controllers/'+self.chain_name+'_traj_controller/trajectory' ,JointTrajectory, queue_size=10) self.positionPublisher = rospy.Publisher('/trajectory_controllers/'+self.chain_name+'_traj_controller/joint_states',JointState, queue_size=10) self.ghostPublisher = rospy.Publisher('/flor/ghost/set_joint_states',JointState, queue_size=10) label.setText(self.chain_name) vbox.addStretch(1) frame.setLayout(vbox) main_hbox.addWidget(frame)
def create_label_textedit_pair(key, value): param_layout = QHBoxLayout() name_widget = QLabel(key) textedit_widget = QTextEdit() textedit_widget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored) textedit_widget.setMinimumSize(0, 30) textedit_widget.append(str(value)) param_layout.addWidget(name_widget) param_layout.addWidget(textedit_widget) return param_layout
def _create_find_frame(self): find_frame = QFrame(self) find_hbox_layout = QHBoxLayout(find_frame) find_hbox_layout.setContentsMargins(0, 0, 0, 0) find_hbox_layout.setSpacing(1) self.search_field = EnchancedLineEdit(find_frame) self.search_field.setPlaceholderText('search text') self.search_field.textChanged.connect(self.on_search_text_changed) self.search_field.returnPressed.connect(self.on_search) find_hbox_layout.addWidget(self.search_field) self.search_result_label = QLabel(find_frame) self.search_result_label.setText(' ') find_hbox_layout.addWidget(self.search_result_label) self.find_button_back = QPushButton("<") self.find_button_back.setFixedWidth(44) self.find_button_back.clicked.connect(self.on_search_back) find_hbox_layout.addWidget(self.find_button_back) self.find_button = QPushButton(">") self.find_button.setDefault(True) # self.find_button.setFlat(True) self.find_button.setFixedWidth(44) self.find_button.clicked.connect(self.on_search) find_hbox_layout.addWidget(self.find_button) return find_frame
def __init__(self, nodename, masteruri, loggername, level='INFO', parent=None): ''' Creates a new item. ''' QFrame.__init__(self, parent) self.setObjectName("LoggerItem") self.nodename = nodename self.masteruri = masteruri self.loggername = loggername self.current_level = None layout = QHBoxLayout(self) layout.setContentsMargins(1, 1, 1, 1) self.debug = QRadioButton() self.debug.setStyleSheet( "QRadioButton{ background-color: #39B54A;}") # QColor(57, 181, 74) self.debug.toggled.connect(self.toggled_debug) layout.addWidget(self.debug) self.info = QRadioButton() self.info.setStyleSheet("QRadioButton{ background-color: #FFFAFA;}") self.info.toggled.connect(self.toggled_info) layout.addWidget(self.info) self.warn = QRadioButton() self.warn.setStyleSheet( "QRadioButton{ background-color: #FFC706;}") # QColor(255, 199, 6) self.warn.toggled.connect(self.toggled_warn) layout.addWidget(self.warn) self.error = QRadioButton() self.error.setStyleSheet( "QRadioButton{ background-color: #DE382B;}") # QColor(222, 56, 43) self.error.toggled.connect(self.toggled_error) layout.addWidget(self.error) self.fatal = QRadioButton() self.fatal.setStyleSheet("QRadioButton{ background-color: #FF0000;}") self.fatal.toggled.connect(self.toggled_fatal) layout.addWidget(self.fatal) self.label = QLabel(loggername) layout.addWidget(self.label) layout.addStretch() self._callback = None # used to set all logger self.success_signal.connect(self.on_succes_update) self.error_signal.connect(self.on_error_update) self.set_level(level)
def __init__(self): super(CalibrationMovementsGUI, self).__init__() self.handeye_client = HandeyeClient() self.current_target_pose = -1 # -1 is home self.target_poses = None self.plan_was_successful = None self.state = CalibrationMovementsGUI.NOT_INITED_YET self.layout = QVBoxLayout() self.labels_layout = QHBoxLayout() self.buttons_layout = QHBoxLayout() self.progress_bar = QProgressBar() self.pose_number_lbl = QLabel('0/0') self.bad_plan_lbl = QLabel('No plan yet') self.bad_plan_lbl.setAlignment(Qt.AlignCenter) self.guide_lbl = QLabel('Hello') self.guide_lbl.setWordWrap(True) self.check_start_pose_btn = QPushButton('Check starting pose') self.check_start_pose_btn.clicked.connect( self.handle_check_current_state) self.next_pose_btn = QPushButton('Next Pose') self.next_pose_btn.clicked.connect(self.handle_next_pose) self.plan_btn = QPushButton('Plan') self.plan_btn.clicked.connect(self.handle_plan) self.execute_btn = QPushButton('Execute') self.execute_btn.clicked.connect(self.handle_execute) self.labels_layout.addWidget(self.pose_number_lbl) self.labels_layout.addWidget(self.bad_plan_lbl) self.buttons_layout.addWidget(self.check_start_pose_btn) self.buttons_layout.addWidget(self.next_pose_btn) self.buttons_layout.addWidget(self.plan_btn) self.buttons_layout.addWidget(self.execute_btn) self.layout.addWidget(self.progress_bar) self.layout.addLayout(self.labels_layout) self.layout.addWidget(self.guide_lbl) self.layout.addLayout(self.buttons_layout) self.setLayout(self.layout) self.plan_btn.setEnabled(False) self.execute_btn.setEnabled(False) self.setWindowTitle('Local Mover') self.show()
def _read_next_item(self): (qid, text, data) = self._queue.get() if qid == self.TYPE_NOSCREEN: self.questionid = self.TYPE_NOSCREEN self.text = 'No screens found! See log for details!<br>The following nodes are affected:' self.data = data self.frameui.questionIcon.setPixmap(self.IMAGES[qid]) self.frameui.questionLabel.setText(self.text) for nodename in data.data: self.frameui.scrollAreaLayout.addWidget(QLabel(nodename)) self.frameui.scrollArea.setVisible(True) elif qid != self.TYPE_INVALID: self.questionid = qid self.text = text self.data = data self.frameui.questionIcon.setPixmap(self.IMAGES[qid]) self.frameui.questionLabel.setText(text) return qid != self.TYPE_INVALID
def __init__(self, buttonProgramArrayIterator): super(ButtonSetPopupSelector, self).__init__(); self.setStyleSheet(SpeakEasyGUI.stylesheetAppBG); self.programButtonDict = {}; self.buttonProgramArrayIt = buttonProgramArrayIterator; self.buttonProgramArrays = []; # saved ButtonProgram arrays self.shownLabelArrays = []; self.currentlyShowingSetIndex = None; self.rootLayout = None; self.cancelButton = QPushButton("Cancel"); self.cancelButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); self.cancelButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); #self.cancelButton.clicked.connect(partial(QDialog.done, self, 0)); self.cancelButton.clicked.connect(self.clickedCancelButton); self.OKButton = QPushButton("Pick this One"); self.OKButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); self.OKButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); self.OKButton.clicked.connect(self.clickedOKButton); self.currentNextPrevDirection = NextPrev.NEXT; self.nextButton = QPushButton("Next"); self.nextButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); self.nextButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); self.nextButton.clicked.connect(self.clickedNextButton); self.prevButton = QPushButton("Previous"); self.prevButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); self.prevButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); self.prevButton.clicked.connect(self.clickedPrevButton); self.setNextPrevButtonsEnabledness(); self.endOfSetsLabel = QLabel("<b>No more button sets.</b>") self.noSetsLabel = QLabel("<b>No button sets available.</b>") self.noAvailableSets = False; self.offerNewButtonSet();
def startPropertyEdit(self): self.editing_properties = True self.edit_existing_location = self.edit_properties_location self.edit_area_button[LocationFunction.ADD_LOCATION_AREA].setEnabled( True) self.edit_area_button[LocationFunction.EDIT_EXISTING_AREA].setEnabled( True) # Construct the configuration layout. clearLayoutAndFixHeight(self.configuration_layout) neighbors_str = makeNeighborsString( self.locations[self.edit_properties_location], self.locations) self.update_name_label = QLabel( "Location (" + self.edit_properties_location + " - " + neighbors_str + ") New Name: ", self.widget) self.configuration_layout.addWidget(self.update_name_label) self.update_name_textedit = QLineEdit(self.widget) self.update_name_textedit.setText(self.edit_properties_location) self.update_name_textedit.textEdited.connect( self.locationNameTextEdited) self.configuration_layout.addWidget(self.update_name_textedit) self.update_name_button = QPushButton("Update location Name", self.widget) self.update_name_button.clicked[bool].connect(self.updateLocationName) self.update_name_button.setEnabled(False) self.configuration_layout.addWidget(self.update_name_button) self.remove_location_button = QPushButton("Remove Location", self.widget) self.remove_location_button.clicked[bool].connect( self.removeCurrentLocation) self.configuration_layout.addWidget(self.remove_location_button) self.configuration_layout.addStretch(1) self.updateOverlay()
def __init__(self, context): super(PingGUI, self).__init__(context) # Give QObjects reasonable names self.setObjectName("PingGUI") self.msg = None # Create a container widget and give it a layout self._container = QWidget() self._layout = QVBoxLayout() self._container.setLayout(self._layout) self._label = QLabel("xx ms latency") p = self._label.palette() p.setColor(self._label.backgroundRole(), Qt.red) self._label.setPalette(p) self._layout.addWidget(self._label) self.set_bg_color(100, 100, 100) rospy.Subscriber("/ping/delay", Float64, self.ping_cb) context.add_widget(self._container) self._update_plot_timer = QTimer(self) self._update_plot_timer.timeout.connect(self.update_gui) self._update_plot_timer.start(1)
def __init__(self, masteruri, cfg, ns, nodes, parent=None): QFrame.__init__(self, parent) self._masteruri = masteruri self._nodes = {cfg: {ns: nodes}} frame_layout = QVBoxLayout(self) frame_layout.setContentsMargins(0, 0, 0, 0) # create frame for warning label self.warning_frame = warning_frame = QFrame(self) warning_layout = QHBoxLayout(warning_frame) warning_layout.setContentsMargins(0, 0, 0, 0) warning_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.warning_label = QLabel() icon = QIcon(':/icons/crystal_clear_warning.png') self.warning_label.setPixmap(icon.pixmap(QSize(40, 40))) self.warning_label.setToolTip('Multiple configuration for same node found!\nA first one will be selected for the start a node!') warning_layout.addWidget(self.warning_label) warning_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) frame_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) frame_layout.addWidget(warning_frame) # create frame for start/stop buttons buttons_frame = QFrame() buttons_layout = QHBoxLayout(buttons_frame) buttons_layout.setContentsMargins(0, 0, 0, 0) buttons_layout.addItem(QSpacerItem(20, 20)) self.on_button = QPushButton() self.on_button.setFlat(False) self.on_button.setText("On") self.on_button.clicked.connect(self.on_on_clicked) buttons_layout.addWidget(self.on_button) self.off_button = QPushButton() self.off_button.setFlat(True) self.off_button.setText("Off") self.off_button.clicked.connect(self.on_off_clicked) buttons_layout.addWidget(self.off_button) buttons_layout.addItem(QSpacerItem(20, 20)) frame_layout.addWidget(buttons_frame) frame_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.warning_frame.setVisible(False)
def __init__(self, context): # super(BDIPelvisPoseWidget, self).__init__(context) # self.setObjectName('BDIPelvisPoseWidget') super(BDIPelvisPoseWidget, self).__init__() self.name = "BDIPelvisPoseWidget" self.updateStateSignal.connect(self.on_updateState) # self._widget = QWidget() self._widget = context vbox = QVBoxLayout() self.forward_position = 0.0 self.lateral_position = 0.0 self.height_position = 0.91 self.roll_position = 0.0 self.pitch_position = 0.0 self.yaw_position = 0.0 self.currentForward = 0.0 self.currentLateral = 0.0 self.currentHeight = 0.91 self.currentRoll = 0.0 self.currentPitch = 0.0 self.currentYaw = 0.0 # Define checkboxes vbox = QVBoxLayout() label = QLabel() label.setText("BDI Pelvis Height (Manipulate Mode Only)") # todo - connect controller mode vbox.addWidget(label) self.enable_checkbox = QCheckBox("Enable") self.enable_checkbox.stateChanged.connect(self.on_enable_check) vbox.addWidget(self.enable_checkbox) self.snap_to_current_button = QPushButton("Snap to Current") self.snap_to_current_button.pressed.connect(self.on_snapCurrentPressed) vbox.addWidget(self.snap_to_current_button) self.roll_slider = QSlider(Qt.Horizontal) self.roll_label = QLabel() self.roll_label.setText("Roll") vbox.addWidget(self.roll_label) self.roll_slider.setRange(int(-100), int(101)) self.roll_slider.setValue(int(0)) self.roll_slider.setSingleStep((200) / 50) self.roll_slider.setTickInterval(25) self.roll_slider.valueChanged.connect(self.on_rollSliderMoved) vbox.addWidget(self.roll_slider) self.roll_progress_bar = QProgressBar() self.roll_progress_bar.setRange(int(-100), int(101)) self.roll_progress_bar.setValue((6.0 / math.pi) * self.currentRoll * 100) self.roll_progress_bar.setFormat("%.6f" % self.currentRoll) vbox.addWidget(self.roll_progress_bar) self.pitch_slider = QSlider(Qt.Horizontal) self.pitch_label = QLabel() self.pitch_label.setText("Pitch") vbox.addWidget(self.pitch_label) self.pitch_slider.setRange(int(-100), int(101)) self.pitch_slider.setValue(int(0)) self.pitch_slider.setSingleStep((200) / 50) self.pitch_slider.setTickInterval(25) self.pitch_slider.valueChanged.connect(self.on_pitchSliderMoved) vbox.addWidget(self.pitch_slider) self.pitch_progress_bar = QProgressBar() self.pitch_progress_bar.setRange(int(-100), int(101)) self.pitch_progress_bar.setValue((6.0 / math.pi) * self.currentPitch * 100) self.pitch_progress_bar.setFormat("%.6f" % self.currentPitch) vbox.addWidget(self.pitch_progress_bar) self.yaw_slider = QSlider(Qt.Horizontal) self.yaw_label = QLabel() self.yaw_label.setText("Yaw") vbox.addWidget(self.yaw_label) self.yaw_slider.setRange(int(-100), int(101)) self.yaw_slider.setValue(int(0)) self.yaw_slider.setSingleStep((200) / 50) self.yaw_slider.setTickInterval(25) self.yaw_slider.valueChanged.connect(self.on_yawSliderMoved) vbox.addWidget(self.yaw_slider) self.yaw_progress_bar = QProgressBar() self.yaw_progress_bar.setRange(int(-100), int(101)) self.yaw_progress_bar.setValue((4.0 / math.pi) * self.currentYaw * 100) self.yaw_progress_bar.setFormat("%.6f" % self.currentYaw) vbox.addWidget(self.yaw_progress_bar) self.forward_label = QLabel() self.forward_label.setText("Forward") vbox.addWidget(self.forward_label) widget = QWidget() hbox = QHBoxLayout() hbox.addStretch() self.forward_slider = QSlider(Qt.Vertical) # self.forward_slider.setText("Height") self.forward_slider.setRange(int(-101), int(100)) self.forward_slider.setValue(int(0)) self.forward_slider.setSingleStep(1) self.forward_slider.setTickInterval(10) self.forward_slider.valueChanged.connect(self.on_forwardSliderMoved) hbox.addWidget(self.forward_slider) self.forward_progress_bar = QProgressBar() self.forward_progress_bar.setOrientation(Qt.Vertical) self.forward_progress_bar.setRange(int(-100), int(101)) self.forward_progress_bar.setValue((self.currentForward / 0.075) * 100) self.forward_progress_bar.setTextVisible(False) hbox.addWidget(self.forward_progress_bar) self.forward_progress_bar_label = QLabel() self.forward_progress_bar_label.setText("%.6f" % self.currentForward) hbox.addWidget(self.forward_progress_bar_label) hbox.addStretch() widget.setLayout(hbox) vbox.addWidget(widget) self.lateral_label = QLabel() self.lateral_label.setText("Lateral") vbox.addWidget(self.lateral_label) self.lateral_slider = QSlider(Qt.Horizontal) # self.lateral_slider.setText("Lateral") self.lateral_slider.setRange(int(-100), int(101)) self.lateral_slider.setValue(int(0)) self.lateral_slider.setSingleStep((200) / 50) self.lateral_slider.setTickInterval(25) self.lateral_slider.valueChanged.connect(self.on_lateralSliderMoved) vbox.addWidget(self.lateral_slider) self.lateral_progress_bar = QProgressBar() self.lateral_progress_bar.setRange(int(-100), int(101)) self.lateral_progress_bar.setValue((self.currentLateral / 0.15) * 100) self.lateral_progress_bar.setFormat("%.6f" % self.currentLateral) vbox.addWidget(self.lateral_progress_bar) self.height_label = QLabel() self.height_label.setText("Height") vbox.addWidget(self.height_label) widget = QWidget() hbox = QHBoxLayout() hbox.addStretch() self.height_slider = QSlider(Qt.Vertical) # self.height_slider.setText("Height") self.height_slider.setRange(int(55), int(105)) self.height_slider.setValue(int(91)) self.height_slider.setSingleStep(2) self.height_slider.setTickInterval(10) self.height_slider.valueChanged.connect(self.on_heightSliderMoved) hbox.addWidget(self.height_slider) self.height_progress_bar = QProgressBar() self.height_progress_bar.setOrientation(Qt.Vertical) self.height_progress_bar.setRange(int(55), int(105)) self.height_progress_bar.setValue(self.currentHeight * 100) self.height_progress_bar.setTextVisible(False) hbox.addWidget(self.height_progress_bar) self.height_progress_bar_label = QLabel() self.height_progress_bar_label.setText("%.6f" % self.currentHeight) hbox.addWidget(self.height_progress_bar_label) hbox.addStretch() widget.setLayout(hbox) vbox.addWidget(widget) vbox.addStretch() self._widget.setLayout(vbox) # context.add_widget(self._widget) self.height_position = 0.91 self.lateral_position = 0.0 self.yaw_position = 0.0 self.first_time = True self.enable_checkbox.setChecked(False) self.yaw_slider.setEnabled(False) self.roll_slider.setEnabled(False) self.pitch_slider.setEnabled(False) self.forward_slider.setEnabled(False) self.lateral_slider.setEnabled(False) self.height_slider.setEnabled(False) self.pub_robot = rospy.Publisher("/flor/controller/bdi_desired_pelvis_pose", PoseStamped, queue_size=10) # self.stateSubscriber = rospy.Subscriber('/flor/pelvis_controller/current_states',JointState, self.stateCallbackFnc) # self.pub_bdi_pelvis = rospy.Publisher('/bdi_manipulate_pelvis_pose_rpy',PoseStamped) self.pelvis_trajectory_pub = rospy.Publisher( "/robot_controllers/pelvis_traj_controller/command", JointTrajectory, queue_size=10 ) self.stateSubscriber = rospy.Subscriber( "/robot_controllers/pelvis_traj_controller/state", JointTrajectoryControllerState, self.stateCallbackFnc )
class TextSearchFrame(QDockWidget): ''' A frame to find text in the Editor. ''' search_result_signal = Signal(str, bool, str, int) ''' @ivar: A signal emitted after search_threaded was started. (search text, found or not, file, position in text) for each result a signal will be emitted. ''' replace_signal = Signal(str, str, int, str) ''' @ivar: A signal emitted to replace string at given position. (search text, file, position in text, replaced by text) ''' def __init__(self, tabwidget, parent=None): QDockWidget.__init__(self, "Find", parent) self.setObjectName('SearchFrame') self.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable) self._dockwidget = QFrame(self) self.vbox_layout = QVBoxLayout(self._dockwidget) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().setSpacing(1) # frame with two rows for find and replace find_replace_frame = QFrame(self) find_replace_vbox_layout = QVBoxLayout(find_replace_frame) find_replace_vbox_layout.setContentsMargins(0, 0, 0, 0) find_replace_vbox_layout.setSpacing(1) # find_replace_vbox_layout.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding, QSizePolicy.Expanding)) # create frame with find row find_frame = self._create_find_frame() find_replace_vbox_layout.addWidget(find_frame) rplc_frame = self._create_replace_frame() find_replace_vbox_layout.addWidget(rplc_frame) # frame for find&replace and search results self.vbox_layout.addWidget(find_replace_frame) self.vbox_layout.addWidget(self._create_found_frame()) # self.vbox_layout.addStretch(2024) self.setWidget(self._dockwidget) # intern search parameters self._tabwidget = tabwidget self.current_search_text = '' self.search_results = [] self.search_results_fileset = set() self._search_result_index = -1 self._search_recursive = False self._search_thread = None def _create_find_frame(self): find_frame = QFrame(self) find_hbox_layout = QHBoxLayout(find_frame) find_hbox_layout.setContentsMargins(0, 0, 0, 0) find_hbox_layout.setSpacing(1) self.search_field = EnchancedLineEdit(find_frame) self.search_field.setPlaceholderText('search text') self.search_field.textChanged.connect(self.on_search_text_changed) self.search_field.returnPressed.connect(self.on_search) find_hbox_layout.addWidget(self.search_field) self.search_result_label = QLabel(find_frame) self.search_result_label.setText(' ') find_hbox_layout.addWidget(self.search_result_label) self.find_button_back = QPushButton("<") self.find_button_back.setFixedWidth(44) self.find_button_back.clicked.connect(self.on_search_back) find_hbox_layout.addWidget(self.find_button_back) self.find_button = QPushButton(">") self.find_button.setDefault(True) # self.find_button.setFlat(True) self.find_button.setFixedWidth(44) self.find_button.clicked.connect(self.on_search) find_hbox_layout.addWidget(self.find_button) return find_frame def _create_replace_frame(self): # create frame with replace row self.rplc_frame = rplc_frame = QFrame(self) rplc_hbox_layout = QHBoxLayout(rplc_frame) rplc_hbox_layout.setContentsMargins(0, 0, 0, 0) rplc_hbox_layout.setSpacing(1) self.replace_field = EnchancedLineEdit(rplc_frame) self.replace_field.setPlaceholderText('replace text') self.replace_field.returnPressed.connect(self.on_replace) rplc_hbox_layout.addWidget(self.replace_field) self.replace_result_label = QLabel(rplc_frame) self.replace_result_label.setText(' ') rplc_hbox_layout.addWidget(self.replace_result_label) self.replace_button = replace_button = QPushButton("> &Replace >") replace_button.setFixedWidth(90) replace_button.clicked.connect(self.on_replace_click) rplc_hbox_layout.addWidget(replace_button) rplc_frame.setVisible(False) return rplc_frame def _create_found_frame(self): ff_frame = QFrame(self) self.found_files_vbox_layout = QVBoxLayout(ff_frame) self.found_files_vbox_layout.setContentsMargins(0, 0, 0, 0) self.recursive_search_box = QCheckBox("recursive search") self.found_files_vbox_layout.addWidget(self.recursive_search_box) self.found_files_list = QTreeWidget(ff_frame) self.found_files_list.setColumnCount(1) self.found_files_list.setFrameStyle(QFrame.StyledPanel) self.found_files_list.setHeaderHidden(True) self.found_files_list.itemActivated.connect(self.on_itemActivated) self.found_files_list.setStyleSheet( "QTreeWidget {" "background-color:transparent;" "}" "QTreeWidget::item {" "background-color:transparent;" "}" "QTreeWidget::item:selected {" "background-color: darkgray;" "}") self.found_files_vbox_layout.addWidget(self.found_files_list) self.recursive_search_box.setChecked(False) return ff_frame def keyPressEvent(self, event): ''' Enable the shortcats for search and replace ''' self.parent().keyPressEvent(event) def on_search(self): ''' Initiate the new search or request a next search result. ''' if self.current_search_text != self.search_field.text() or self._search_recursive != self.recursive_search_box.isChecked(): # clear current search results self._reset() self.current_search_text = self.search_field.text() if self.current_search_text: path_text = {} self._wait_for_result = True for i in range(self._tabwidget.count()): path_text[self._tabwidget.widget(i).filename] = self._tabwidget.widget(i).document().toPlainText() self._search_recursive = self.recursive_search_box.isChecked() self._search_thread = TextSearchThread(self.current_search_text, self._tabwidget.currentWidget().filename, path_text=path_text, recursive=self._search_recursive) self._search_thread.search_result_signal.connect(self.on_search_result) self._search_thread.warning_signal.connect(self.on_warning_result) self._search_thread.start() elif self.search_results: self._check_position() if self.search_results: if self._search_result_index + 1 >= len(self.search_results): self._search_result_index = -1 self._search_result_index += 1 (id, search_text, found, path, index, linenr, line) = self.search_results[self._search_result_index] self.search_result_signal.emit(search_text, found, path, index) self.replace_button.setEnabled(True) self._update_label() def on_search_back(self): ''' Slot to handle the search back function. ''' self._check_position(False) if self.search_results: self._search_result_index -= 1 if self._search_result_index < 0: self._search_result_index = len(self.search_results) - 1 self._update_label() (id, search_text, found, path, index, linenr, line) = self.search_results[self._search_result_index] self.search_result_signal.emit(search_text, found, path, index) self.replace_button.setEnabled(True) def _check_position(self, forward=True): try: # if the position of the textCursor was changed by the user, move the search index cur_pos = self._tabwidget.currentWidget().textCursor().position() id, st, _f, pa, idx, lnr, ltxt = self.search_results[self._search_result_index] sear_pos = idx + len(st) if cur_pos != sear_pos: first_idx = self._get_current_index_for_current_file() if first_idx != -1: id, st, _f, pa, idx, lnr, ltxt = self.search_results[first_idx] sear_pos = idx + len(st) while cur_pos > sear_pos and self._tabwidget.currentWidget().filename == pa: first_idx += 1 id, st, _f, pa, idx, lnr, ltxt = self.search_results[first_idx] sear_pos = idx + len(st) self._search_result_index = first_idx if forward: self._search_result_index -= 1 else: self._reset(True) except: pass def _get_current_index_for_current_file(self): for index in range(len(self.search_results)): id, _st, _f, pa, _idx = self.search_results[index] if self._tabwidget.currentWidget().filename == pa: return index return -1 def on_search_result(self, search_text, found, path, index, linenr, line): ''' Slot to handle the signals for search result. This signals are forwarded used search_result_signal. ''' if found and search_text == self.current_search_text: id = "%d:%s" % (index, path) self.search_results_fileset.add(path) item = (search_text, found, path, index) if item not in self.search_results: self.search_results.append((id, search_text, found, path, index, linenr, line)) if self._wait_for_result: self._search_result_index += 1 if index >= self._tabwidget.currentWidget().textCursor().position() or self._tabwidget.currentWidget().filename != path: self._wait_for_result = False self.search_result_signal.emit(search_text, found, path, index) self.replace_button.setEnabled(True) pkg, rpath = package_name(os.path.dirname(path)) itemstr = '%s [%s]' % (os.path.basename(path), pkg) if not self.found_files_list.findItems(itemstr, Qt.MatchExactly): list_item = QTreeWidgetItem(self.found_files_list) list_item.setText(0, itemstr) list_item.setToolTip(0, path) self.found_files_list.insertTopLevelItem(0, list_item) self.found_files_list.expandAll() for i in range(self.found_files_list.topLevelItemCount()): top_item = self.found_files_list.topLevelItem(i) if top_item.text(0) == itemstr: sub_item_str = "%d: %s" % (linenr, line) list_item2 = QTreeWidgetItem() list_item2.setText(0, sub_item_str) list_item2.setWhatsThis(0, id) top_item.addChild(list_item2) #self.found_files_list.setVisible(len(self.search_results_fileset) > 0) self._update_label() def on_warning_result(self, text): rospy.logwarn(text) def on_replace_click(self): self.on_replace() self.on_search() def on_replace(self): ''' Emits the replace signal, but only if currently selected text is equal to the searched one. ''' if self.search_results: try: id, search_text, _found, path, index, linenr, line_text = self.search_results[self._search_result_index] cursor = self._tabwidget.currentWidget().textCursor() if cursor.selectedText() == search_text: rptxt = self.replace_field.text() for rindex in range(self._search_result_index + 1, len(self.search_results)): iid, st, _f, pa, idx, lnr, ltxt = self.search_results[rindex] if path == pa: self.search_results.pop(rindex) self.search_results.insert(rindex, (iid, st, _f, pa, idx + len(rptxt) - len(st), lnr, ltxt)) else: break self._remove_search_result(self._search_result_index) self._search_result_index -= 1 self.replace_signal.emit(search_text, path, index, rptxt) else: self.replace_button.setEnabled(False) except: import traceback print traceback.format_exc() pass def on_itemActivated(self, item): ''' Go to the results for the selected file entry in the list. ''' splits = item.whatsThis(0).split(':') if len(splits) == 2: item_index = int(splits[0]) item_path = splits[1] new_search_index = -1 tmp_index = -1 search_index = -1 tmp_search_text = '' for id, search_text, found, path, index, linenr, line_text in self.search_results: new_search_index += 1 if item_path == path and item_index == index: self._search_result_index = new_search_index self.search_result_signal.emit(search_text, found, path, index) self._update_label() def on_search_text_changed(self, _text): ''' Clear search result if the text was changed. ''' self._reset() def _update_label(self, clear_label=False): ''' Updates the status label for search results. The info is created from search result lists. ''' msg = ' ' if self.search_results: count_files = len(self.search_results_fileset) msg = '%d/%d' % (self._search_result_index + 1, len(self.search_results)) if count_files > 1: msg = '%s(%d)' % (msg, count_files) if self._search_thread is not None and self._search_thread.is_alive(): msg = 'searching..%s' % msg elif not msg.strip() and self.current_search_text: msg = '0 found' self.current_search_text = '' if clear_label: msg = ' ' self.search_result_label.setText(msg) self.find_button_back.setEnabled(len(self.search_results)) self._select_current_item_in_box(self._search_result_index) def file_changed(self, path): ''' Clears search results if for changed file are some search results are available :param path: changed file path :type path: str ''' if path in self.search_results_fileset: self._reset() def set_replace_visible(self, value): self.rplc_frame.setVisible(value) self.raise_() self.activateWindow() if value: self.replace_field.setFocus() self.replace_field.selectAll() self.setWindowTitle("Find / Replace") else: self.setWindowTitle("Find") self.search_field.setFocus() def is_replace_visible(self): return self.rplc_frame.isVisible() def _reset(self, force_new_search=False): # clear current search results if self._search_thread is not None: self._search_thread.search_result_signal.disconnect() self._search_thread.stop() self._search_thread = None self.current_search_text = '' self.search_results = [] self.search_results_fileset = set() self.found_files_list.clear() # self.found_files_list.setVisible(False) self._update_label(True) self._search_result_index = -1 self.find_button_back.setEnabled(False) if force_new_search: self.on_search() def enable(self): self.setVisible(True) # self.show() self.raise_() self.activateWindow() self.search_field.setFocus() self.search_field.selectAll() def _select_current_item_in_box(self, index): try: (id, search_text, found, path, index, linenr, line) = self.search_results[index] for topidx in range(self.found_files_list.topLevelItemCount()): topitem = self.found_files_list.topLevelItem(topidx) for childdx in range(topitem.childCount()): child = topitem.child(childdx) if child.whatsThis(0) == id: child.setSelected(True) elif child.isSelected(): child.setSelected(False) except: pass def _remove_search_result(self, index): try: (id, search_text, found, path, index, linenr, line) = self.search_results.pop(index) pkg, rpath = package_name(os.path.dirname(path)) itemstr = '%s [%s]' % (os.path.basename(path), pkg) found_items = self.found_files_list.findItems(itemstr, Qt.MatchExactly) for item in found_items: for chi in range(item.childCount()): child = item.child(chi) if child.whatsThis(0) == id: item.removeChild(child) break # delete top level item if it is now empty for topidx in range(self.found_files_list.topLevelItemCount()): if self.found_files_list.topLevelItem(topidx).childCount() == 0: self.found_files_list.takeTopLevelItem(topidx) break # create new set with files contain the search text new_path_set = set(path for _id, _st, _fd, path, _idx, lnr, lntxt in self.search_results) self.search_results_fileset = new_path_set # self.found_files_list.setVisible(len(self.search_results_fileset) > 0) except: import traceback print traceback.format_exc()
class SelectDialog(QDialog): ''' This dialog creates an input mask for a string list and return selected entries. ''' def __init__(self, items=list(), buttons=QDialogButtonBox.Cancel | QDialogButtonBox.Ok, exclusive=False, preselect_all=False, title='', description='', icon='', parent=None, select_if_single=True, checkitem1='', checkitem2=''): ''' Creates an input dialog. @param items: a list with strings @type items: C{list()} ''' QDialog.__init__(self, parent=parent) self.setObjectName(' - '.join(['SelectDialog', str(items)])) self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) # add filter row self.filter_frame = QFrame(self) filterLayout = QHBoxLayout(self.filter_frame) filterLayout.setContentsMargins(1, 1, 1, 1) label = QLabel("Filter:", self.filter_frame) self.filter_field = EnchancedLineEdit(self.filter_frame) filterLayout.addWidget(label) filterLayout.addWidget(self.filter_field) self.filter_field.textChanged.connect(self._on_filter_changed) self.verticalLayout.addWidget(self.filter_frame) if description: self.description_frame = QFrame(self) descriptionLayout = QHBoxLayout(self.description_frame) # descriptionLayout.setContentsMargins(1, 1, 1, 1) if icon: self.icon_label = QLabel(self.description_frame) self.icon_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.icon_label.setPixmap(QPixmap(icon).scaled(30, 30, Qt.KeepAspectRatio)) descriptionLayout.addWidget(self.icon_label) self.description_label = QLabel(self.description_frame) self.description_label.setWordWrap(True) self.description_label.setText(description) descriptionLayout.addWidget(self.description_label) self.verticalLayout.addWidget(self.description_frame) # create area for the parameter self.content = MainBox(self) if items: self.scroll_area = QScrollArea(self) self.scroll_area.setFocusPolicy(Qt.NoFocus) self.scroll_area.setObjectName("scroll_area") self.scroll_area.setWidgetResizable(True) self.scroll_area.setWidget(self.content) self.verticalLayout.addWidget(self.scroll_area) self.checkitem1 = checkitem1 self.checkitem1_result = False self.checkitem2 = checkitem2 self.checkitem2_result = False # add select all option if not exclusive and items: self._ignore_next_toggle = False self.select_all_checkbox = QCheckBox('all entries') self.select_all_checkbox.setTristate(True) self.select_all_checkbox.stateChanged.connect(self._on_select_all_checkbox_stateChanged) self.verticalLayout.addWidget(self.select_all_checkbox) self.content.toggled.connect(self._on_main_toggle) if self.checkitem1: self.checkitem1_checkbox = QCheckBox(self.checkitem1) self.checkitem1_checkbox.stateChanged.connect(self._on_select_checkitem1_checkbox_stateChanged) self.verticalLayout.addWidget(self.checkitem1_checkbox) if self.checkitem2: self.checkitem2_checkbox = QCheckBox(self.checkitem2) self.checkitem2_checkbox.stateChanged.connect(self._on_select_checkitem2_checkbox_stateChanged) self.verticalLayout.addWidget(self.checkitem2_checkbox) if not items: spacerItem = QSpacerItem(1, 1, QSizePolicy.Expanding, QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) # create buttons self.buttonBox = QDialogButtonBox(self) self.buttonBox.setObjectName("buttonBox") self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(buttons) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.verticalLayout.addWidget(self.buttonBox) # set the input fields if items: self.content.createFieldsFromValues(items, exclusive) if (select_if_single and len(items) == 1) or preselect_all: self.select_all_checkbox.setCheckState(Qt.Checked) if not items or len(items) < 7: self.filter_frame.setVisible(False) # print '=============== create', self.objectName() # # def __del__(self): # print "************ destroy", self.objectName() def _on_main_toggle(self, state): self._ignore_next_toggle = state != self.select_all_checkbox.checkState() self.select_all_checkbox.setCheckState(state) def _on_select_all_checkbox_stateChanged(self, state): if not self._ignore_next_toggle: self.content.setState(state) self._ignore_next_toggle = False def _on_select_checkitem1_checkbox_stateChanged(self, state): if state == Qt.Checked: self.checkitem1_result = True elif state == Qt.Unchecked: self.checkitem1_result = False def _on_select_checkitem2_checkbox_stateChanged(self, state): if state == Qt.Checked: self.checkitem2_result = True elif state == Qt.Unchecked: self.checkitem2_result = False def _on_filter_changed(self): self.content.filter(self.filter_field.text()) def getSelected(self): return self.content.getSelected() @staticmethod def getValue(title, description='', items=list(), exclusive=False, preselect_all=False, icon='', parent=None, select_if_single=True, checkitem1='', checkitem2=''): selectDia = SelectDialog(items, exclusive=exclusive, preselect_all=preselect_all, description=description, icon=icon, parent=parent, select_if_single=select_if_single, checkitem1=checkitem1, checkitem2=checkitem2) selectDia.setWindowTitle(title) selectDia.resize(480, 256) if selectDia.exec_(): if selectDia.checkitem2: return selectDia.getSelected(), True, selectDia.checkitem1_result, selectDia.checkitem2_result if selectDia.checkitem1: return selectDia.getSelected(), True, selectDia.checkitem1_result return selectDia.getSelected(), True if selectDia.checkitem2: return list(), False, False, False if selectDia.checkitem1: return list(), False, False return list(), False # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # %%%%%%%%%%%%%%%%%% close handling %%%%%%%%%%%%%%%%%%%%% # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% def accept(self): self.setResult(QDialog.Accepted) self.hide() def reject(self): self.setResult(QDialog.Rejected) self.hide() def hideEvent(self, event): self.close() def closeEvent(self, event): ''' Test the open files for changes and save this if needed. ''' self.setAttribute(Qt.WA_DeleteOnClose, True) QDialog.closeEvent(self, event)
class CapabilityControlWidget(QFrame): ''' The control widget contains buttons for control a capability. Currently this are C{On} and C{Off} buttons. Additionally, the state of the capability is color coded. ''' start_nodes_signal = Signal(str, str, list) '''@ivar: the signal is emitted to start on host(described by masteruri) the nodes described in the list, Parameter(masteruri, config, nodes).''' stop_nodes_signal = Signal(str, list) '''@ivar: the signal is emitted to stop on masteruri the nodes described in the list.''' def __init__(self, masteruri, cfg, ns, nodes, parent=None): QFrame.__init__(self, parent) self._masteruri = masteruri self._nodes = {cfg: {ns: nodes}} frame_layout = QVBoxLayout(self) frame_layout.setContentsMargins(0, 0, 0, 0) # create frame for warning label self.warning_frame = warning_frame = QFrame(self) warning_layout = QHBoxLayout(warning_frame) warning_layout.setContentsMargins(0, 0, 0, 0) warning_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.warning_label = QLabel() icon = QIcon(':/icons/crystal_clear_warning.png') self.warning_label.setPixmap(icon.pixmap(QSize(40, 40))) self.warning_label.setToolTip('Multiple configuration for same node found!\nA first one will be selected for the start a node!') warning_layout.addWidget(self.warning_label) warning_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) frame_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) frame_layout.addWidget(warning_frame) # create frame for start/stop buttons buttons_frame = QFrame() buttons_layout = QHBoxLayout(buttons_frame) buttons_layout.setContentsMargins(0, 0, 0, 0) buttons_layout.addItem(QSpacerItem(20, 20)) self.on_button = QPushButton() self.on_button.setFlat(False) self.on_button.setText("On") self.on_button.clicked.connect(self.on_on_clicked) buttons_layout.addWidget(self.on_button) self.off_button = QPushButton() self.off_button.setFlat(True) self.off_button.setText("Off") self.off_button.clicked.connect(self.on_off_clicked) buttons_layout.addWidget(self.off_button) buttons_layout.addItem(QSpacerItem(20, 20)) frame_layout.addWidget(buttons_frame) frame_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding)) self.warning_frame.setVisible(False) def hasConfigs(self): ''' @return: True, if a configurations for this widget are available. @rtype: bool ''' return len(self._nodes) > 0 def nodes(self, cfg=''): ''' @return: the list with nodes required by this capability. The nodes are defined by ROS full name. @rtype: C{[str]} ''' try: if cfg: return [n for l in self._nodes[cfg].itervalues() for n in l] else: return [n for c in self._nodes.itervalues() for l in c.itervalues() for n in l] except: return [] def setNodeState(self, running_nodes, stopped_nodes, error_nodes): ''' Sets the state of this capability. @param running_nodes: a list with running nodes. @type running_nodes: C{[str]} @param stopped_nodes: a list with not running nodes. @type stopped_nodes: C{[str]} @param error_nodes: a list with nodes having a problem. @type error_nodes: C{[str]} ''' self.setAutoFillBackground(True) self.setBackgroundRole(QPalette.Base) palette = QPalette() if error_nodes: brush = QBrush(QColor(255, 100, 0)) elif running_nodes and stopped_nodes: brush = QBrush(QColor(140, 185, 255)) # 30, 50, 255 elif running_nodes: self.on_button.setFlat(True) self.off_button.setFlat(False) brush = QBrush(QColor(59, 223, 18)) # 59, 223, 18 else: brush = QBrush(QColor(255, 255, 255)) self.on_button.setFlat(False) self.off_button.setFlat(True) palette.setBrush(QPalette.Active, QPalette.Base, brush) brush.setStyle(Qt.SolidPattern) palette.setBrush(QPalette.Inactive, QPalette.Base, brush) self.setPalette(palette) def removeCfg(self, cfg): try: del self._nodes[cfg] except: pass def updateNodes(self, cfg, ns, nodes): self._nodes[cfg] = {ns: nodes} test_nodes = self.nodes() self.warning_frame.setVisible(len(test_nodes) != len(set(test_nodes))) def on_on_clicked(self): started = set() # do not start nodes multiple times for c in self._nodes.iterkeys(): node2start = set(self.nodes(c)) - started self.start_nodes_signal.emit(self._masteruri, c, list(node2start)) started.update(node2start) self.on_button.setFlat(True) self.off_button.setFlat(False) def on_off_clicked(self): self.stop_nodes_signal.emit(self._masteruri, self.nodes()) self.on_button.setFlat(False) self.off_button.setFlat(True)
class ParamWidget(QWidget): _TITLE_PLUGIN = 'Dynamic Reconfigure' # To be connected to PluginContainerWidget sig_sysmsg = Signal(str) sig_sysprogress = Signal(str) # To make selections from CLA sig_selected = Signal(str) def __init__(self, context, node=None): """ This class is intended to be called by rqt plugin framework class. Currently (12/12/2012) the whole widget is splitted into 2 panes: one on left allows you to choose the node(s) you work on. Right side pane lets you work with the parameters associated with the node(s) you select on the left. (12/27/2012) Despite the pkg name is changed to rqt_reconfigure to reflect the available functionality, file & class names remain 'param', expecting all the parameters will become handle-able. """ super(ParamWidget, self).__init__() self.setObjectName(self._TITLE_PLUGIN) self.setWindowTitle(self._TITLE_PLUGIN) rp = rospkg.RosPack() #TODO: .ui file needs to replace the GUI components declaration # below. For unknown reason, referring to another .ui files # from a .ui that is used in this class failed. So for now, # I decided not use .ui in this class. # If someone can tackle this I'd appreciate. _hlayout_top = QHBoxLayout(self) _hlayout_top.setContentsMargins(QMargins(0, 0, 0, 0)) self._splitter = QSplitter(self) _hlayout_top.addWidget(self._splitter) _vlayout_nodesel_widget = QWidget() _vlayout_nodesel_side = QVBoxLayout() _hlayout_filter_widget = QWidget(self) _hlayout_filter = QHBoxLayout() self._text_filter = TextFilter() self.filter_lineedit = TextFilterWidget(self._text_filter, rp) self.filterkey_label = QLabel("&Filter key:") self.filterkey_label.setBuddy(self.filter_lineedit) _hlayout_filter.addWidget(self.filterkey_label) _hlayout_filter.addWidget(self.filter_lineedit) _hlayout_filter_widget.setLayout(_hlayout_filter) self._nodesel_widget = NodeSelectorWidget(self, rp, self.sig_sysmsg) _vlayout_nodesel_side.addWidget(_hlayout_filter_widget) _vlayout_nodesel_side.addWidget(self._nodesel_widget) _vlayout_nodesel_side.setSpacing(1) _vlayout_nodesel_widget.setLayout(_vlayout_nodesel_side) reconf_widget = ParameditWidget(rp) self._splitter.insertWidget(0, _vlayout_nodesel_widget) self._splitter.insertWidget(1, reconf_widget) # 1st column, _vlayout_nodesel_widget, to minimize width. # 2nd col to keep the possible max width. self._splitter.setStretchFactor(0, 0) self._splitter.setStretchFactor(1, 1) # Signal from paramedit widget to node selector widget. reconf_widget.sig_node_disabled_selected.connect( self._nodesel_widget.node_deselected) # Pass name of node to editor widget self._nodesel_widget.sig_node_selected.connect( reconf_widget.show_reconf) if not node: title = self._TITLE_PLUGIN else: title = self._TITLE_PLUGIN + ' %s' % node self.setObjectName(title) #Connect filter signal-slots. self._text_filter.filter_changed_signal.connect( self._filter_key_changed) # Open any clients indicated from command line self.sig_selected.connect(self._nodesel_widget.node_selected) for rn in [rospy.resolve_name(c) for c in context.argv()]: if rn in self._nodesel_widget.get_paramitems(): self.sig_selected.emit(rn) else: rospy.logwarn('Could not find a dynamic reconfigure client named \'%s\'', str(rn)) def shutdown(self): #TODO: Needs implemented. Trigger dynamic_reconfigure to unlatch # subscriber. pass def save_settings(self, plugin_settings, instance_settings): instance_settings.set_value('splitter', self._splitter.saveState()) 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]) def get_filter_text(self): """ :rtype: QString """ return self.filter_lineedit.text() def _filter_key_changed(self): self._nodesel_widget.set_filter(self._text_filter) #TODO: This method should be integrated into common architecture. I just # can't think of how to do so within current design. def emit_sysmsg(self, msg_str): self.sig_sysmsg.emit(msg_str)
class PingGUI(Plugin): def __init__(self, context): super(PingGUI, self).__init__(context) # Give QObjects reasonable names self.setObjectName("PingGUI") self.msg = None # Create a container widget and give it a layout self._container = QWidget() self._layout = QVBoxLayout() self._container.setLayout(self._layout) self._label = QLabel("xx ms latency") p = self._label.palette() p.setColor(self._label.backgroundRole(), Qt.red) self._label.setPalette(p) self._layout.addWidget(self._label) self.set_bg_color(100, 100, 100) rospy.Subscriber("/ping/delay", Float64, self.ping_cb) context.add_widget(self._container) self._update_plot_timer = QTimer(self) self._update_plot_timer.timeout.connect(self.update_gui) self._update_plot_timer.start(1) def update_gui(self): if not self.msg: return msg = self.msg # msec # 100 -> green, 1000 -> red # normalize within 1000 ~ 100 orig_latency = msg.data msg_data = orig_latency if msg.data > 1000: msg_data = 1000 elif msg.data < 100: msg_data = 100 ratio = (msg_data - 100) / (1000 - 100) color_r = ratio * 255.0 color_g = (1 - ratio) * 255.0 # devnull = open(os.devnull, "w") # with RedirectStdStreams(stdout=devnull, stderr=devnull): self.set_bg_color(color_r, color_g, 0) self._label.setText("%d ms latency" % (orig_latency)) def set_bg_color(self, r, g, b): self._label.setStyleSheet( "QLabel { display: block; background-color: rgba(%d, %d, %d, 255); text-align: center; font-size: 30px;}" % (r, g, b) ) def ping_cb(self, msg): self.msg = msg def shutdown_plugin(self): pass def save_settings(self, plugin_settings, instance_settings): pass def restore_settings(self, plugin_settings, instance_settings): pass
def __init__(self, items=list(), buttons=QDialogButtonBox.Cancel | QDialogButtonBox.Ok, exclusive=False, preselect_all=False, title='', description='', icon='', parent=None, select_if_single=True, checkitem1='', checkitem2=''): ''' Creates an input dialog. @param items: a list with strings @type items: C{list()} ''' QDialog.__init__(self, parent=parent) self.setObjectName(' - '.join(['SelectDialog', str(items)])) self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setContentsMargins(1, 1, 1, 1) # add filter row self.filter_frame = QFrame(self) filterLayout = QHBoxLayout(self.filter_frame) filterLayout.setContentsMargins(1, 1, 1, 1) label = QLabel("Filter:", self.filter_frame) self.filter_field = EnchancedLineEdit(self.filter_frame) filterLayout.addWidget(label) filterLayout.addWidget(self.filter_field) self.filter_field.textChanged.connect(self._on_filter_changed) self.verticalLayout.addWidget(self.filter_frame) if description: self.description_frame = QFrame(self) descriptionLayout = QHBoxLayout(self.description_frame) # descriptionLayout.setContentsMargins(1, 1, 1, 1) if icon: self.icon_label = QLabel(self.description_frame) self.icon_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.icon_label.setPixmap(QPixmap(icon).scaled(30, 30, Qt.KeepAspectRatio)) descriptionLayout.addWidget(self.icon_label) self.description_label = QLabel(self.description_frame) self.description_label.setWordWrap(True) self.description_label.setText(description) descriptionLayout.addWidget(self.description_label) self.verticalLayout.addWidget(self.description_frame) # create area for the parameter self.content = MainBox(self) if items: self.scroll_area = QScrollArea(self) self.scroll_area.setFocusPolicy(Qt.NoFocus) self.scroll_area.setObjectName("scroll_area") self.scroll_area.setWidgetResizable(True) self.scroll_area.setWidget(self.content) self.verticalLayout.addWidget(self.scroll_area) self.checkitem1 = checkitem1 self.checkitem1_result = False self.checkitem2 = checkitem2 self.checkitem2_result = False # add select all option if not exclusive and items: self._ignore_next_toggle = False self.select_all_checkbox = QCheckBox('all entries') self.select_all_checkbox.setTristate(True) self.select_all_checkbox.stateChanged.connect(self._on_select_all_checkbox_stateChanged) self.verticalLayout.addWidget(self.select_all_checkbox) self.content.toggled.connect(self._on_main_toggle) if self.checkitem1: self.checkitem1_checkbox = QCheckBox(self.checkitem1) self.checkitem1_checkbox.stateChanged.connect(self._on_select_checkitem1_checkbox_stateChanged) self.verticalLayout.addWidget(self.checkitem1_checkbox) if self.checkitem2: self.checkitem2_checkbox = QCheckBox(self.checkitem2) self.checkitem2_checkbox.stateChanged.connect(self._on_select_checkitem2_checkbox_stateChanged) self.verticalLayout.addWidget(self.checkitem2_checkbox) if not items: spacerItem = QSpacerItem(1, 1, QSizePolicy.Expanding, QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) # create buttons self.buttonBox = QDialogButtonBox(self) self.buttonBox.setObjectName("buttonBox") self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(buttons) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.verticalLayout.addWidget(self.buttonBox) # set the input fields if items: self.content.createFieldsFromValues(items, exclusive) if (select_if_single and len(items) == 1) or preselect_all: self.select_all_checkbox.setCheckState(Qt.Checked) if not items or len(items) < 7: self.filter_frame.setVisible(False)
class ButtonSetPopupSelector(QDialog): ''' An interactive dialog that displays successive sets of buttons. When each set is displayed, user may ask for the next available set, the previous. already seen set, or the user may accept the currently displayed set. A cancel is available as well. The call and return protocol is as follows: - The caller creates a fresh dialog instance of this class, passing an iterator. The iterator's next() method returns an array of ButtonProgram instances each time it is called. (When the iterator is exhausted, the user is able to use a 'Previous' button to view the previously seen sets again). - The caller invokes the exec_() method on the dialog instance. - The exec_() method returns: - -1, if the iterator yielded no button label arrays at all. - 0, if the user canceled, and - 1 if the user accepted one of the sets. - If the exec_() method returned 1, the caller may obtain an array with the ButtonProgram instances of the currently showing (and therefore accepted) buttons. The array is obtained from the dialog instance via method getCurrentlyShowingSetLabels(self). ''' #------------------------------------------------------ Public Methods --------------------------- def __init__(self, buttonProgramArrayIterator): super(ButtonSetPopupSelector, self).__init__(); self.setStyleSheet(SpeakEasyGUI.stylesheetAppBG); self.programButtonDict = {}; self.buttonProgramArrayIt = buttonProgramArrayIterator; self.buttonProgramArrays = []; # saved ButtonProgram arrays self.shownLabelArrays = []; self.currentlyShowingSetIndex = None; self.rootLayout = None; self.cancelButton = QPushButton("Cancel"); self.cancelButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); self.cancelButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); #self.cancelButton.clicked.connect(partial(QDialog.done, self, 0)); self.cancelButton.clicked.connect(self.clickedCancelButton); self.OKButton = QPushButton("Pick this One"); self.OKButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); self.OKButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); self.OKButton.clicked.connect(self.clickedOKButton); self.currentNextPrevDirection = NextPrev.NEXT; self.nextButton = QPushButton("Next"); self.nextButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); self.nextButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); self.nextButton.clicked.connect(self.clickedNextButton); self.prevButton = QPushButton("Previous"); self.prevButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); self.prevButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); self.prevButton.clicked.connect(self.clickedPrevButton); self.setNextPrevButtonsEnabledness(); self.endOfSetsLabel = QLabel("<b>No more button sets.</b>") self.noSetsLabel = QLabel("<b>No button sets available.</b>") self.noAvailableSets = False; self.offerNewButtonSet(); def exec_(self): ''' If the prior initialization revealed that the caller does not deliver any sets of button labels at all, then return -1, without displaying any dialog. @return: -1 if no button sets available. 1 if user accepted one of the button label sets as the one they want, or 0, if the user cancelled. @rtype: int ''' if self.noAvailableSets: return -1; return super(ButtonSetPopupSelector, self).exec_(); def getCurrentlyShowingSet(self): ''' Returns an array of ButtonProgram instances that are currently showing on the dialog, or were showing when the user clicked OK. @return: Array of ButtonProgram instances. @rtype: [ButtonProgram] ''' return self.buttonProgramArrays[self.currentlyShowingSetIndex]; def getCurrentlyShowingSetLabels(self): ''' Returns an array of labels of buttons that are currently showing on the dialog, or were showing when the user clicked OK. @return: Array of labels. @rtype: [string] ''' allLabels = []; for buttonProgram in self.buttonProgramArrays[self.currentlyShowingSetIndex]: allLabels.append(buttonProgram.getLabel()); return allLabels; #------------------------------------------------------ Private Methods --------------------------- def offerNewButtonSet(self): ''' Responsible for displaying the next, or previous set of buttons. During successive calls to this method, the method obtains new button label sets from the caller's iterator until the iterator is exhausted. The sets are collected in <code>self.shownLabelArrays</code>. The method is also responsible for showing previously shown sets again. The direction is controlled by the handlers of the Previous and Next buttons. They set instance variable <code>currentNextPrevDirection</code>. ''' # Make sure the 'No more button sets in this direction" # message gets deleted: self.endOfSetsLabel.hide(); self.enableActionButton(self.OKButton); # Want to display a previously displayed button set? if self.currentNextPrevDirection == NextPrev.PREVIOUS: # Are we showing the first set, i.e. is there no set # before the current one? if self.currentlyShowingSetIndex == 0: # Show the 'nothing before this one' label, # and switch directions: self.flipNextPrevDirection(); return; self.currentlyShowingSetIndex -= 1; self.buildButtonSet(self.getCurrentlyShowingSetLabels()); #*************** self.setButtonSetTitleInWindow(self.currentlyShowingSetIndex + 1); #*************** self.setNextPrevButtonsEnabledness(); return; # Wants next button set. Is there one we haven't shown yet?: try: # Get next set of ButtonProgram instances from caller: buttonProgramArray = self.buttonProgramArrayIt.next(); # Save this ButtonProgram instance: self.buttonProgramArrays.append(buttonProgramArray); # From the ButtonProgram objects array, create an # array of just the button labels: buttonLabelArray = []; for buttonProgram in buttonProgramArray: buttonLabelArray.append(buttonProgram.getLabel()); # If this is the very first time we pull a button set # from the caller, then our current index will be None # from the initialization. We use that to check for # the case that the caller has no sets at all to feed # out. Since we didn't bomb with StopIteration, we know # that there is at least one available button set: if self.currentlyShowingSetIndex is None: self.currentlyShowingSetIndex = -1; # Save that list of button names: self.shownLabelArrays.append(buttonLabelArray); self.currentlyShowingSetIndex += 1; #********** self.setButtonSetTitleInWindow(self.currentlyShowingSetIndex + 1); #********** self.buildButtonSet(buttonLabelArray); self.setNextPrevButtonsEnabledness(); return; except StopIteration: # If we fell through the very first time, there is no # button set available at all: if self.currentlyShowingSetIndex is None: self.terminateWithWarning(); return; # No more button sets available from caller's iterator: self.currentlyShowingSetIndex += 1; #********** self.setButtonSetTitleInWindow(self.currentlyShowingSetIndex + 1); #********** if self.currentlyShowingSetIndex >= len(self.shownLabelArrays): # Neither are there more new sets, nor are we going # through the already shown sets going forward a second # time. So reverse direction to go backwards through the # the already shown sets: self.setButtonSetTitleInWindow(-1) self.flipNextPrevDirection(); return; self.buildButtonSet(self.getCurrentlyShowingSetLabels()); self.setNextPrevButtonsEnabledness(); return; def setButtonSetTitleInWindow(self, buttonSetIndex): ''' Given a button set number, displays a help text in the 'pick button set' dialog. @param buttonSetIndex: number of button set (1-based by convention, but 0 is legal). set to -1 if wish to indicate absence of a relevant set. Will show as 'Showing button set --'. @type buttonSetIndex: int ''' if buttonSetIndex > -1: self.setWindowTitle('Showing button set %d' % buttonSetIndex); else: self.setWindowTitle('Showing button set --'); def flipNextPrevDirection(self): ''' Called when no more button label sets are available either in the next, or previous direction. ''' self.clearDialogPane(); self.rootLayout.addWidget(self.endOfSetsLabel); # Show the 'End of sets' label, and # de-activate the OK button: self.endOfSetsLabel.show(); self.disableActionButton(self.OKButton); if (self.currentNextPrevDirection == NextPrev.PREVIOUS): self.currentNextPrevDirection = NextPrev.NEXT; self.currentlyShowingSetIndex = -1; else: self.currentNextPrevDirection = NextPrev.PREVIOUS; self.currentlyShowingSetIndex = len(self.shownLabelArrays); self.setNextPrevButtonsEnabledness(); self.addChoiceButtons(self.rootLayout); self.setLayout(self.rootLayout); def clearDialogPane(self): ''' Cleans out the dialog's layout. Does not destroy the control buttons (Next, Previous, Cancel, and OK), but does trigger deletion of all the button objects in the button grid. Attempts to None out references to UI widgets to enable garbage collection. ''' if self.rootLayout is None: return; self.rootLayout.removeWidget(self.cancelButton); self.rootLayout.removeWidget(self.OKButton); self.rootLayout.removeWidget(self.nextButton); self.rootLayout.removeWidget(self.prevButton); self.rootLayout.removeItem(self.buttonGridLayout); self.buttonGritLayout = None; for buttonObj in self.programButtonDict.values(): if buttonObj is not None: buttonObj.hide(); buttonObj.deleteLater() for key in self.programButtonDict.keys(): self.programButtonDict[key] = None; # Set this dialog's layout to the empty layout: self.setLayout(self.rootLayout); def buildButtonSet(self, buttonLabelArray): ''' Constructs one set of buttons, based on passed in button labels. @param buttonLabelArray: Array of button labels. @type buttonLabelArray: [string] ''' # If we never made the root layout, make it now: if self.rootLayout is None: self.rootLayout = QVBoxLayout(); else: # A previous button set is being displayed, # Empty out the rootLayout: self.clearDialogPane(); # Get a layout filled with the button objects # in the proper styling. Also get a dictionary # mapping button labels to button objects: (self.buttonGridLayout, self.programButtonDict) =\ SpeakEasyGUI.buildButtonGrid(buttonLabelArray, SpeakEasyGUI.NUM_OF_PROGRAM_BUTTON_COLUMNS); for buttonObj in self.programButtonDict.values(): buttonObj.setStyleSheet(SpeakEasyGUI.programButtonStylesheet); buttonObj.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT); # Place the grid into a V-layout, and add # the next/previous, cancel, and OK buttons; self.rootLayout.addLayout(self.buttonGridLayout); self.addChoiceButtons(self.rootLayout); # Set the popup window's layout to the button grid # plus choice button combo: self.setLayout(self.rootLayout); def addChoiceButtons(self, layout): ''' Appends the existing Next/Previous/Cancel/OK buttons into the passed-in layout. @param layout: ''' choiceButtonRowLayout = QHBoxLayout(); choiceButtonRowLayout.addWidget(self.nextButton); choiceButtonRowLayout.addWidget(self.prevButton); choiceButtonRowLayout.addWidget(self.cancelButton); choiceButtonRowLayout.addWidget(self.OKButton); layout.addLayout(choiceButtonRowLayout); def setNextPrevButtonsEnabledness(self): ''' Examines the instance variables <code>shownLabelArrays</code> and </code>currentlyShowingSetIndex</code> to determine whether the Next or Previous buttons should be enabled. Acts on the result. ''' if self.currentlyShowingSetIndex >= len(self.shownLabelArrays): # Can only go backwards: self.disableActionButton(self.nextButton); self.enableActionButton(self.prevButton); elif self.currentlyShowingSetIndex <= 0: # Can only go forward: self.enableActionButton(self.nextButton); self.disableActionButton(self.prevButton); else: self.enableActionButton(self.nextButton); self.enableActionButton(self.prevButton); def enableActionButton(self, buttonObj): buttonObj.setEnabled(True) buttonObj.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet); def disableActionButton(self, buttonObj): buttonObj.setEnabled(False) buttonObj.setStyleSheet(SpeakEasyGUI.recorderButtonDisabledStylesheet); def clickedNextButton(self): ''' Handler for Next button clicks. Triggers show of next button set in order. ''' if self.currentNextPrevDirection == NextPrev.PREVIOUS: self.currentNextPrevDirection = NextPrev.NEXT; self.offerNewButtonSet(); def clickedPrevButton(self): ''' Handler for Next button clicks. Triggers show of previous button set in order. ''' if self.currentNextPrevDirection == NextPrev.NEXT: self.currentNextPrevDirection = NextPrev.PREVIOUS; self.offerNewButtonSet(); def clickedCancelButton(self): self.clearDialogPane(); self.done(0); def clickedOKButton(self): self.clearDialogPane(); self.done(1); def terminateWithWarning(self): ''' Called when no button sets are available from the caller at all. Records this event in instance variable <code>noAvailableSets</code>, and returns. ''' # No buttons at all: self.clearDialogPane(); self.noAvailableSets = True;
class BDIPelvisPoseWidget(QObject): updateStateSignal = Signal(object) def __init__(self, context): # super(BDIPelvisPoseWidget, self).__init__(context) # self.setObjectName('BDIPelvisPoseWidget') super(BDIPelvisPoseWidget, self).__init__() self.name = "BDIPelvisPoseWidget" self.updateStateSignal.connect(self.on_updateState) # self._widget = QWidget() self._widget = context vbox = QVBoxLayout() self.forward_position = 0.0 self.lateral_position = 0.0 self.height_position = 0.91 self.roll_position = 0.0 self.pitch_position = 0.0 self.yaw_position = 0.0 self.currentForward = 0.0 self.currentLateral = 0.0 self.currentHeight = 0.91 self.currentRoll = 0.0 self.currentPitch = 0.0 self.currentYaw = 0.0 # Define checkboxes vbox = QVBoxLayout() label = QLabel() label.setText("BDI Pelvis Height (Manipulate Mode Only)") # todo - connect controller mode vbox.addWidget(label) self.enable_checkbox = QCheckBox("Enable") self.enable_checkbox.stateChanged.connect(self.on_enable_check) vbox.addWidget(self.enable_checkbox) self.snap_to_current_button = QPushButton("Snap to Current") self.snap_to_current_button.pressed.connect(self.on_snapCurrentPressed) vbox.addWidget(self.snap_to_current_button) self.roll_slider = QSlider(Qt.Horizontal) self.roll_label = QLabel() self.roll_label.setText("Roll") vbox.addWidget(self.roll_label) self.roll_slider.setRange(int(-100), int(101)) self.roll_slider.setValue(int(0)) self.roll_slider.setSingleStep((200) / 50) self.roll_slider.setTickInterval(25) self.roll_slider.valueChanged.connect(self.on_rollSliderMoved) vbox.addWidget(self.roll_slider) self.roll_progress_bar = QProgressBar() self.roll_progress_bar.setRange(int(-100), int(101)) self.roll_progress_bar.setValue((6.0 / math.pi) * self.currentRoll * 100) self.roll_progress_bar.setFormat("%.6f" % self.currentRoll) vbox.addWidget(self.roll_progress_bar) self.pitch_slider = QSlider(Qt.Horizontal) self.pitch_label = QLabel() self.pitch_label.setText("Pitch") vbox.addWidget(self.pitch_label) self.pitch_slider.setRange(int(-100), int(101)) self.pitch_slider.setValue(int(0)) self.pitch_slider.setSingleStep((200) / 50) self.pitch_slider.setTickInterval(25) self.pitch_slider.valueChanged.connect(self.on_pitchSliderMoved) vbox.addWidget(self.pitch_slider) self.pitch_progress_bar = QProgressBar() self.pitch_progress_bar.setRange(int(-100), int(101)) self.pitch_progress_bar.setValue((6.0 / math.pi) * self.currentPitch * 100) self.pitch_progress_bar.setFormat("%.6f" % self.currentPitch) vbox.addWidget(self.pitch_progress_bar) self.yaw_slider = QSlider(Qt.Horizontal) self.yaw_label = QLabel() self.yaw_label.setText("Yaw") vbox.addWidget(self.yaw_label) self.yaw_slider.setRange(int(-100), int(101)) self.yaw_slider.setValue(int(0)) self.yaw_slider.setSingleStep((200) / 50) self.yaw_slider.setTickInterval(25) self.yaw_slider.valueChanged.connect(self.on_yawSliderMoved) vbox.addWidget(self.yaw_slider) self.yaw_progress_bar = QProgressBar() self.yaw_progress_bar.setRange(int(-100), int(101)) self.yaw_progress_bar.setValue((4.0 / math.pi) * self.currentYaw * 100) self.yaw_progress_bar.setFormat("%.6f" % self.currentYaw) vbox.addWidget(self.yaw_progress_bar) self.forward_label = QLabel() self.forward_label.setText("Forward") vbox.addWidget(self.forward_label) widget = QWidget() hbox = QHBoxLayout() hbox.addStretch() self.forward_slider = QSlider(Qt.Vertical) # self.forward_slider.setText("Height") self.forward_slider.setRange(int(-101), int(100)) self.forward_slider.setValue(int(0)) self.forward_slider.setSingleStep(1) self.forward_slider.setTickInterval(10) self.forward_slider.valueChanged.connect(self.on_forwardSliderMoved) hbox.addWidget(self.forward_slider) self.forward_progress_bar = QProgressBar() self.forward_progress_bar.setOrientation(Qt.Vertical) self.forward_progress_bar.setRange(int(-100), int(101)) self.forward_progress_bar.setValue((self.currentForward / 0.075) * 100) self.forward_progress_bar.setTextVisible(False) hbox.addWidget(self.forward_progress_bar) self.forward_progress_bar_label = QLabel() self.forward_progress_bar_label.setText("%.6f" % self.currentForward) hbox.addWidget(self.forward_progress_bar_label) hbox.addStretch() widget.setLayout(hbox) vbox.addWidget(widget) self.lateral_label = QLabel() self.lateral_label.setText("Lateral") vbox.addWidget(self.lateral_label) self.lateral_slider = QSlider(Qt.Horizontal) # self.lateral_slider.setText("Lateral") self.lateral_slider.setRange(int(-100), int(101)) self.lateral_slider.setValue(int(0)) self.lateral_slider.setSingleStep((200) / 50) self.lateral_slider.setTickInterval(25) self.lateral_slider.valueChanged.connect(self.on_lateralSliderMoved) vbox.addWidget(self.lateral_slider) self.lateral_progress_bar = QProgressBar() self.lateral_progress_bar.setRange(int(-100), int(101)) self.lateral_progress_bar.setValue((self.currentLateral / 0.15) * 100) self.lateral_progress_bar.setFormat("%.6f" % self.currentLateral) vbox.addWidget(self.lateral_progress_bar) self.height_label = QLabel() self.height_label.setText("Height") vbox.addWidget(self.height_label) widget = QWidget() hbox = QHBoxLayout() hbox.addStretch() self.height_slider = QSlider(Qt.Vertical) # self.height_slider.setText("Height") self.height_slider.setRange(int(55), int(105)) self.height_slider.setValue(int(91)) self.height_slider.setSingleStep(2) self.height_slider.setTickInterval(10) self.height_slider.valueChanged.connect(self.on_heightSliderMoved) hbox.addWidget(self.height_slider) self.height_progress_bar = QProgressBar() self.height_progress_bar.setOrientation(Qt.Vertical) self.height_progress_bar.setRange(int(55), int(105)) self.height_progress_bar.setValue(self.currentHeight * 100) self.height_progress_bar.setTextVisible(False) hbox.addWidget(self.height_progress_bar) self.height_progress_bar_label = QLabel() self.height_progress_bar_label.setText("%.6f" % self.currentHeight) hbox.addWidget(self.height_progress_bar_label) hbox.addStretch() widget.setLayout(hbox) vbox.addWidget(widget) vbox.addStretch() self._widget.setLayout(vbox) # context.add_widget(self._widget) self.height_position = 0.91 self.lateral_position = 0.0 self.yaw_position = 0.0 self.first_time = True self.enable_checkbox.setChecked(False) self.yaw_slider.setEnabled(False) self.roll_slider.setEnabled(False) self.pitch_slider.setEnabled(False) self.forward_slider.setEnabled(False) self.lateral_slider.setEnabled(False) self.height_slider.setEnabled(False) self.pub_robot = rospy.Publisher("/flor/controller/bdi_desired_pelvis_pose", PoseStamped, queue_size=10) # self.stateSubscriber = rospy.Subscriber('/flor/pelvis_controller/current_states',JointState, self.stateCallbackFnc) # self.pub_bdi_pelvis = rospy.Publisher('/bdi_manipulate_pelvis_pose_rpy',PoseStamped) self.pelvis_trajectory_pub = rospy.Publisher( "/robot_controllers/pelvis_traj_controller/command", JointTrajectory, queue_size=10 ) self.stateSubscriber = rospy.Subscriber( "/robot_controllers/pelvis_traj_controller/state", JointTrajectoryControllerState, self.stateCallbackFnc ) def stateCallbackFnc(self, jointState_msg): self.updateStateSignal.emit(jointState_msg) def shutdown_plugin(self): # Just make sure to stop timers and publishers, unsubscribe from Topics etc in the shutdown_plugin method. print "Shutdown BDI pelvis height " self.pub_robot.unregister() self.stateSubscriber.unregister() def publishRobotPelvisPose(self): print "publishing new pelvis pose ..." bdi_pelvis_pose = PoseStamped() bdi_pelvis_pose.header.stamp = rospy.Time.now() bdi_pelvis_pose.pose.position.x = self.forward_position bdi_pelvis_pose.pose.position.y = self.lateral_position bdi_pelvis_pose.pose.position.z = self.height_position # Use BDI yaw*roll*pitch concatenation xaxis, yaxis, zaxis = (1, 0, 0), (0, 1, 0), (0, 0, 1) Rx = tf.transformations.rotation_matrix(self.roll_position, xaxis) Ry = tf.transformations.rotation_matrix(self.pitch_position, yaxis) Rz = tf.transformations.rotation_matrix(self.yaw_position, zaxis) R = tf.transformations.concatenate_matrices(Rz, Rx, Ry) q = tf.transformations.quaternion_from_matrix(R) bdi_pelvis_pose.pose.orientation.w = q[3] bdi_pelvis_pose.pose.orientation.x = q[0] bdi_pelvis_pose.pose.orientation.y = q[1] bdi_pelvis_pose.pose.orientation.z = q[2] # w = math.cos(self.yaw_position*0.5) # bdi_pelvis_pose.pose.orientation.x = 0.0 # bdi_pelvis_pose.pose.orientation.y = 0.0 # bdi_pelvis_pose.pose.orientation.z = math.sin(self.yaw_position*0.5) print bdi_pelvis_pose print q euler = tf.transformations.euler_from_quaternion(q) print euler self.pub_robot.publish(bdi_pelvis_pose) # Now publish the trajectory form for the new controllers trajectory = JointTrajectory() trajectory.header.stamp = rospy.Time.now() trajectory.joint_names = ["com_v1", "com_v0", "pelvis_height", "pelvis_roll", "pelvis_pitch", "pelvis_yaw"] trajectory.points = [JointTrajectoryPoint()] trajectory.points[0].positions = [ self.lateral_position, self.forward_position, self.height_position, self.roll_position, self.pitch_position, self.yaw_position, ] trajectory.points[0].velocities = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] trajectory.points[0].time_from_start = rospy.Duration(0.75) self.pelvis_trajectory_pub.publish(trajectory) ################################### def on_snapCurrentPressed(self): print "Snap ", self.name, " values to current pelvis positions" self.blockSignals(True) self.resetCurrentPelvisSliders() self.blockSignals(False) def blockSignals(self, block): self.yaw_slider.blockSignals(block) self.roll_slider.blockSignals(block) self.pitch_slider.blockSignals(block) self.forward_slider.blockSignals(block) self.lateral_slider.blockSignals(block) self.height_slider.blockSignals(block) def resetCurrentPelvisSliders(self): self.yaw_slider.setValue((4.0 / math.pi) * self.currentYaw * 100) self.roll_slider.setValue((6.0 / math.pi) * self.currentRoll * 100) self.pitch_slider.setValue((6.0 / math.pi) * self.currentPitch * 100) self.forward_slider.setValue((self.currentForward / 0.075) * 100) self.lateral_slider.setValue((self.currentLateral / 0.15) * 100) self.height_slider.setValue(self.currentHeight * 100) self.yaw_label.setText("Yaw: " + str(self.currentYaw)) self.roll_label.setText("Roll: " + str(self.currentRoll)) self.pitch_label.setText("Pitch: " + str(self.currentPitch)) self.forward_label.setText("Forward: " + str(self.currentForward)) self.lateral_label.setText("Lateral: " + str(self.currentLateral)) self.height_label.setText("Height: " + str(self.currentHeight)) self.forward_position = self.currentForward self.lateral_position = self.currentLateral self.height_position = self.currentHeight self.roll_position = self.currentRoll self.pitch_position = self.currentPitch self.yaw_position = self.currentYaw def on_updateState(self, jointState_msg): self.currentLateral = jointState_msg.actual.positions[0] self.currentForward = jointState_msg.actual.positions[1] self.currentHeight = jointState_msg.actual.positions[2] self.currentRoll = jointState_msg.actual.positions[3] self.currentPitch = jointState_msg.actual.positions[4] self.currentYaw = jointState_msg.actual.positions[5] self.yaw_progress_bar.setValue((4.0 / math.pi) * self.currentYaw * 100) self.yaw_progress_bar.setFormat("%.6f" % self.currentYaw) self.roll_progress_bar.setValue((6.0 / math.pi) * self.currentRoll * 100) self.roll_progress_bar.setFormat("%.6f" % self.currentRoll) self.pitch_progress_bar.setValue((6.0 / math.pi) * self.currentPitch * 100) self.pitch_progress_bar.setFormat("%.6f" % self.currentPitch) self.forward_progress_bar.setValue((self.currentForward / 0.075) * 100) self.forward_progress_bar_label.setText("%.6f" % self.currentForward) self.lateral_progress_bar.setValue((self.currentLateral / 0.15) * 100) self.lateral_progress_bar.setFormat("%.6f" % self.currentYaw) self.height_progress_bar.setValue(self.currentHeight * 100) self.height_progress_bar_label.setText("%.6f" % self.currentHeight) #################################### def on_enable_check(self, value): print "Toggle the enabling checkbox - current state is ", value self.yaw_slider.setEnabled(self.enable_checkbox.isChecked()) self.roll_slider.setEnabled(self.enable_checkbox.isChecked()) self.pitch_slider.setEnabled(self.enable_checkbox.isChecked()) self.forward_slider.setEnabled(self.enable_checkbox.isChecked()) self.lateral_slider.setEnabled(self.enable_checkbox.isChecked()) self.height_slider.setEnabled(self.enable_checkbox.isChecked()) def on_yawSliderMoved(self, value): self.yaw_position = (value / 100.0) * math.pi / 4.0 # print "New yaw=",self.yaw_position self.yaw_label.setText("Yaw: " + str(self.yaw_position)) if self.enable_checkbox.isChecked(): self.publishRobotPelvisPose() def on_rollSliderMoved(self, value): self.roll_position = (value / 100.0) * math.pi / 6.0 self.roll_label.setText("Roll: " + str(self.roll_position)) if self.enable_checkbox.isChecked(): self.publishRobotPelvisPose() def on_pitchSliderMoved(self, value): self.pitch_position = (value / 100.0) * math.pi / 6.0 self.pitch_label.setText("Pitch: " + str(self.pitch_position)) if self.enable_checkbox.isChecked(): self.publishRobotPelvisPose() def on_forwardSliderMoved(self, value): self.forward_position = (value / 100.0) * 0.075 # print "New forward=",self.forward_position self.forward_label.setText("Forward: " + str(self.forward_position)) if self.enable_checkbox.isChecked(): self.publishRobotPelvisPose() def on_lateralSliderMoved(self, value): self.lateral_position = (value / 100.0) * 0.15 # print "New lateral=",self.lateral_position self.lateral_label.setText("Lateral: " + str(self.lateral_position)) if self.enable_checkbox.isChecked(): self.publishRobotPelvisPose() def on_heightSliderMoved(self, value): self.height_position = value / 100.0 # print "New height=",self.height_position self.height_label.setText("Height: " + str(self.height_position)) if self.enable_checkbox.isChecked(): self.publishRobotPelvisPose()
class GroupWidget(QWidget): ''' (Isaac's guess as of 12/13/2012) This class bonds multiple Editor instances that are associated with a single node as a group. ''' # public signal sig_node_disabled_selected = Signal(str) def __init__(self, updater, config, nodename): ''' :param config: :type config: Dictionary? defined in dynamic_reconfigure.client.Client :type nodename: str ''' #TODO figure out what data type 'config' is. It is afterall returned # from dynamic_reconfigure.client.get_parameter_descriptions() # ros.org/doc/api/dynamic_reconfigure/html/dynamic_reconfigure.client-pysrc.html#Client super(GroupWidget, self).__init__() self.state = config['state'] self.name = config['name'] self._toplevel_treenode_name = nodename # TODO: .ui file needs to be back into usage in later phase. # ui_file = os.path.join(rp.get_path('rqt_reconfigure'), # 'resource', 'singlenode_parameditor.ui') # loadUi(ui_file, self) verticalLayout = QVBoxLayout(self) verticalLayout.setContentsMargins(QMargins(0, 0, 0, 0)) _widget_nodeheader = QWidget() _h_layout_nodeheader = QHBoxLayout(_widget_nodeheader) _h_layout_nodeheader.setContentsMargins(QMargins(0, 0, 0, 0)) self.nodename_qlabel = QLabel(self) font = QFont('Trebuchet MS, Bold') font.setUnderline(True) font.setBold(True) # Button to close a node. _icon_disable_node = QIcon.fromTheme('window-close') _bt_disable_node = QPushButton(_icon_disable_node, '', self) _bt_disable_node.setToolTip('Hide this node') _bt_disable_node_size = QSize(36, 24) _bt_disable_node.setFixedSize(_bt_disable_node_size) _bt_disable_node.pressed.connect(self._node_disable_bt_clicked) _h_layout_nodeheader.addWidget(self.nodename_qlabel) _h_layout_nodeheader.addWidget(_bt_disable_node) self.nodename_qlabel.setAlignment(Qt.AlignCenter) font.setPointSize(10) self.nodename_qlabel.setFont(font) grid_widget = QWidget(self) self.grid = QFormLayout(grid_widget) verticalLayout.addWidget(_widget_nodeheader) verticalLayout.addWidget(grid_widget, 1) # Again, these UI operation above needs to happen in .ui file. self.tab_bar = None # Every group can have one tab bar self.tab_bar_shown = False self.updater = updater self.editor_widgets = [] self._param_names = [] self._create_node_widgets(config) rospy.logdebug('Groups node name={}'.format(nodename)) self.nodename_qlabel.setText(nodename) # Labels should not stretch #self.grid.setColumnStretch(1, 1) #self.setLayout(self.grid) def collect_paramnames(self, config): pass def _create_node_widgets(self, config): ''' :type config: Dict? ''' i_debug = 0 for param in config['parameters']: begin = time.time() * 1000 editor_type = '(none)' if param['edit_method']: widget = EnumEditor(self.updater, param) elif param['type'] in EDITOR_TYPES: rospy.logdebug('GroupWidget i_debug=%d param type =%s', i_debug, param['type']) editor_type = EDITOR_TYPES[param['type']] widget = eval(editor_type)(self.updater, param) self.editor_widgets.append(widget) self._param_names.append(param['name']) rospy.logdebug('groups._create_node_widgets num editors=%d', i_debug) end = time.time() * 1000 time_elap = end - begin rospy.logdebug('ParamG editor={} loop=#{} Time={}msec'.format( editor_type, i_debug, time_elap)) i_debug += 1 for name, group in config['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._create_node_widgets ' + #'num groups=%d' + 'name=%s', name) for i, ed in enumerate(self.editor_widgets): ed.display(self.grid) rospy.logdebug('GroupWdgt._create_node_widgets len(editor_widgets)=%d', len(self.editor_widgets)) 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 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 get_treenode_names(self): ''' :rtype: str[] ''' return self._param_names def _node_disable_bt_clicked(self): rospy.logdebug('param_gs _node_disable_bt_clicked') self.sig_node_disabled_selected.emit(self._toplevel_treenode_name)
def __init__(self, parent, fileName, widget): self.controllers = [] self.parent = parent self.loadFile(fileName) robot = URDF.from_parameter_server() joint_list = {} for ndx,jnt in enumerate(robot.joints): joint_list[jnt.name] = ndx for controller in self.controllers: frame = QFrame() frame.setFrameShape(QFrame.StyledPanel); frame.setFrameShadow(QFrame.Raised); vbox = QVBoxLayout() label = QLabel() label.setText(controller.label) vbox.addWidget(label); print controller.name controller.snap_to_ghost_button = QPushButton("SnapGhost") controller.snap_to_ghost_button.pressed.connect(controller.on_snapGhostPressed) vbox.addWidget(controller.snap_to_ghost_button) controller.snap_to_current_button = QPushButton("SnapCurrent") controller.snap_to_current_button.pressed.connect(controller.on_snapCurrentPressed) vbox.addWidget(controller.snap_to_current_button) controller.apply_to_robot_button = QPushButton("ApplyRobot") controller.apply_to_robot_button.pressed.connect(controller.on_applyRobotPressed) vbox.addWidget(controller.apply_to_robot_button) controller.save_joints_to_file_button = QPushButton("SaveJoints") controller.save_joints_to_file_button.pressed.connect(controller.on_saveJointsPressed) vbox.addWidget(controller.save_joints_to_file_button) controller.undo_last_action_button = QPushButton("Undo Last") controller.undo_last_action_button.pressed.connect(controller.on_undoPressed) vbox.addWidget(controller.undo_last_action_button) for joint in controller.joints: label = QLabel() label.setText(joint.name) vbox.addWidget(label); robot_joint = robot.joints[joint_list[joint.name]] lower = robot_joint.limit.lower - (math.fabs(robot_joint.limit.upper)+math.fabs(robot_joint.limit.lower))*0.2 upper = robot_joint.limit.upper + (math.fabs(robot_joint.limit.upper)+math.fabs(robot_joint.limit.lower))*0.2 print " ",joint.name, " limits(", robot_joint.limit.lower,", ",robot_joint.limit.upper,") num" joint.slider = QSlider(Qt.Horizontal) joint.slider.setRange(int(lower*10000.0), int(upper*10000.0)) joint.slider.setValue(int(lower*10000.0)) joint.slider.setSingleStep((upper-lower)/20.0) joint.slider.valueChanged.connect(joint.on_sliderMoved) vbox.addWidget(joint.slider) joint.progress_bar = QProgressBar() joint.progress_bar.setRange(int(lower*10000.0), int(upper*10000.0)) joint.progress_bar.setValue(int(lower*10000.0)) vbox.addWidget(joint.progress_bar) vbox.addStretch() frame.setLayout(vbox) widget.addWidget(frame)
def __init__(self, updater, config, nodename): ''' :param config: :type config: Dictionary? defined in dynamic_reconfigure.client.Client :type nodename: str ''' #TODO figure out what data type 'config' is. It is afterall returned # from dynamic_reconfigure.client.get_parameter_descriptions() # ros.org/doc/api/dynamic_reconfigure/html/dynamic_reconfigure.client-pysrc.html#Client super(GroupWidget, self).__init__() self.state = config['state'] self.name = config['name'] self._toplevel_treenode_name = nodename # TODO: .ui file needs to be back into usage in later phase. # ui_file = os.path.join(rp.get_path('rqt_reconfigure'), # 'resource', 'singlenode_parameditor.ui') # loadUi(ui_file, self) verticalLayout = QVBoxLayout(self) verticalLayout.setContentsMargins(QMargins(0, 0, 0, 0)) _widget_nodeheader = QWidget() _h_layout_nodeheader = QHBoxLayout(_widget_nodeheader) _h_layout_nodeheader.setContentsMargins(QMargins(0, 0, 0, 0)) self.nodename_qlabel = QLabel(self) font = QFont('Trebuchet MS, Bold') font.setUnderline(True) font.setBold(True) # Button to close a node. _icon_disable_node = QIcon.fromTheme('window-close') _bt_disable_node = QPushButton(_icon_disable_node, '', self) _bt_disable_node.setToolTip('Hide this node') _bt_disable_node_size = QSize(36, 24) _bt_disable_node.setFixedSize(_bt_disable_node_size) _bt_disable_node.pressed.connect(self._node_disable_bt_clicked) _h_layout_nodeheader.addWidget(self.nodename_qlabel) _h_layout_nodeheader.addWidget(_bt_disable_node) self.nodename_qlabel.setAlignment(Qt.AlignCenter) font.setPointSize(10) self.nodename_qlabel.setFont(font) grid_widget = QWidget(self) self.grid = QFormLayout(grid_widget) verticalLayout.addWidget(_widget_nodeheader) verticalLayout.addWidget(grid_widget, 1) # Again, these UI operation above needs to happen in .ui file. self.tab_bar = None # Every group can have one tab bar self.tab_bar_shown = False self.updater = updater self.editor_widgets = [] self._param_names = [] self._create_node_widgets(config) rospy.logdebug('Groups node name={}'.format(nodename)) self.nodename_qlabel.setText(nodename)
def __init__(self, context, node=None): """ This class is intended to be called by rqt plugin framework class. Currently (12/12/2012) the whole widget is splitted into 2 panes: one on left allows you to choose the node(s) you work on. Right side pane lets you work with the parameters associated with the node(s) you select on the left. (12/27/2012) Despite the pkg name is changed to rqt_reconfigure to reflect the available functionality, file & class names remain 'param', expecting all the parameters will become handle-able. """ super(ParamWidget, self).__init__() self.setObjectName(self._TITLE_PLUGIN) self.setWindowTitle(self._TITLE_PLUGIN) rp = rospkg.RosPack() #TODO: .ui file needs to replace the GUI components declaration # below. For unknown reason, referring to another .ui files # from a .ui that is used in this class failed. So for now, # I decided not use .ui in this class. # If someone can tackle this I'd appreciate. _hlayout_top = QHBoxLayout(self) _hlayout_top.setContentsMargins(QMargins(0, 0, 0, 0)) self._splitter = QSplitter(self) _hlayout_top.addWidget(self._splitter) _vlayout_nodesel_widget = QWidget() _vlayout_nodesel_side = QVBoxLayout() _hlayout_filter_widget = QWidget(self) _hlayout_filter = QHBoxLayout() self._text_filter = TextFilter() self.filter_lineedit = TextFilterWidget(self._text_filter, rp) self.filterkey_label = QLabel("&Filter key:") self.filterkey_label.setBuddy(self.filter_lineedit) _hlayout_filter.addWidget(self.filterkey_label) _hlayout_filter.addWidget(self.filter_lineedit) _hlayout_filter_widget.setLayout(_hlayout_filter) self._nodesel_widget = NodeSelectorWidget(self, rp, self.sig_sysmsg) _vlayout_nodesel_side.addWidget(_hlayout_filter_widget) _vlayout_nodesel_side.addWidget(self._nodesel_widget) _vlayout_nodesel_side.setSpacing(1) _vlayout_nodesel_widget.setLayout(_vlayout_nodesel_side) reconf_widget = ParameditWidget(rp) self._splitter.insertWidget(0, _vlayout_nodesel_widget) self._splitter.insertWidget(1, reconf_widget) # 1st column, _vlayout_nodesel_widget, to minimize width. # 2nd col to keep the possible max width. self._splitter.setStretchFactor(0, 0) self._splitter.setStretchFactor(1, 1) # Signal from paramedit widget to node selector widget. reconf_widget.sig_node_disabled_selected.connect( self._nodesel_widget.node_deselected) # Pass name of node to editor widget self._nodesel_widget.sig_node_selected.connect( reconf_widget.show_reconf) if not node: title = self._TITLE_PLUGIN else: title = self._TITLE_PLUGIN + ' %s' % node self.setObjectName(title) #Connect filter signal-slots. self._text_filter.filter_changed_signal.connect( self._filter_key_changed) # Open any clients indicated from command line self.sig_selected.connect(self._nodesel_widget.node_selected) for rn in [rospy.resolve_name(c) for c in context.argv()]: if rn in self._nodesel_widget.get_paramitems(): self.sig_selected.emit(rn) else: rospy.logwarn('Could not find a dynamic reconfigure client named \'%s\'', str(rn))
def _add_track_label(self, track_name, background_color=None): label = QLabel(track_name) label.setMargin(5) palette = label.palette() palette.setColor(label.foregroundRole(), Qt.black) if background_color is not None: label.setAutoFillBackground(True) palette.setColor(label.backgroundRole(), background_color) label.setPalette(palette) label.setFont(QFont('sans', 13)) self.track_label_layout.addWidget(label)
class Editor(QMainWindow): ''' Creates a dialog to edit a launch file. ''' finished_signal = Signal(list) ''' finished_signal has as parameter the filenames of the initialization and is emitted, if this dialog was closed. ''' def __init__(self, filenames, search_text='', parent=None): ''' @param filenames: a list with filenames. The last one will be activated. @type filenames: C{[str, ...]} @param search_text: if not empty, searches in new document for first occurrence of the given text @type search_text: C{str} (Default: C{Empty String}) ''' QMainWindow.__init__(self, parent) self.setObjectName(' - '.join(['Editor', str(filenames)])) self.setAttribute(Qt.WA_DeleteOnClose, True) self.setWindowFlags(Qt.Window) self.mIcon = QIcon(":/icons/crystal_clear_edit_launch.png") self._error_icon = QIcon(":/icons/crystal_clear_warning.png") self._empty_icon = QIcon() self.setWindowIcon(self.mIcon) window_title = "ROSLaunch Editor" if filenames: window_title = self.__getTabName(filenames[0]) self.setWindowTitle(window_title) self.init_filenames = list(filenames) self._search_thread = None # list with all open files self.files = [] # create tabs for files self.main_widget = QWidget(self) self.verticalLayout = QVBoxLayout(self.main_widget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setSpacing(1) self.verticalLayout.setObjectName("verticalLayout") self.tabWidget = EditorTabWidget(self) self.tabWidget.setTabPosition(QTabWidget.North) self.tabWidget.setDocumentMode(True) self.tabWidget.setTabsClosable(True) self.tabWidget.setMovable(False) self.tabWidget.setObjectName("tabWidget") self.tabWidget.tabCloseRequested.connect(self.on_close_tab) self.verticalLayout.addWidget(self.tabWidget) self.buttons = self._create_buttons() self.verticalLayout.addWidget(self.buttons) self.setCentralWidget(self.main_widget) self.find_dialog = TextSearchFrame(self.tabWidget, self) self.find_dialog.search_result_signal.connect(self.on_search_result) self.find_dialog.replace_signal.connect(self.on_replace) self.addDockWidget(Qt.RightDockWidgetArea, self.find_dialog) # open the files for f in filenames: if f: self.on_load_request(os.path.normpath(f), search_text) self.readSettings() self.find_dialog.setVisible(False) # def __del__(self): # print "******** destroy", self.objectName() def _create_buttons(self): # create the buttons line self.buttons = QWidget(self) self.horizontalLayout = QHBoxLayout(self.buttons) self.horizontalLayout.setContentsMargins(4, 0, 4, 0) self.horizontalLayout.setObjectName("horizontalLayout") # add the search button self.searchButton = QPushButton(self) self.searchButton.setObjectName("searchButton") # self.searchButton.clicked.connect(self.on_shortcut_find) self.searchButton.toggled.connect(self.on_toggled_find) self.searchButton.setText(self._translate("&Find")) self.searchButton.setToolTip('Open a search dialog (Ctrl+F)') self.searchButton.setFlat(True) self.searchButton.setCheckable(True) self.horizontalLayout.addWidget(self.searchButton) # add the replace button self.replaceButton = QPushButton(self) self.replaceButton.setObjectName("replaceButton") # self.replaceButton.clicked.connect(self.on_shortcut_replace) self.replaceButton.toggled.connect(self.on_toggled_replace) self.replaceButton.setText(self._translate("&Replace")) self.replaceButton.setToolTip('Open a search&replace dialog (Ctrl+R)') self.replaceButton.setFlat(True) self.replaceButton.setCheckable(True) self.horizontalLayout.addWidget(self.replaceButton) # add the goto button self.gotoButton = QPushButton(self) self.gotoButton.setObjectName("gotoButton") self.gotoButton.clicked.connect(self.on_shortcut_goto) self.gotoButton.setText(self._translate("&Goto line")) self.gotoButton.setShortcut("Ctrl+G") self.gotoButton.setToolTip('Open a goto dialog (Ctrl+G)') self.gotoButton.setFlat(True) self.horizontalLayout.addWidget(self.gotoButton) # add a tag button self.tagButton = self._create_tag_button(self) self.horizontalLayout.addWidget(self.tagButton) # add spacer spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) # add line number label self.pos_label = QLabel() self.horizontalLayout.addWidget(self.pos_label) # add spacer spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) # add save button self.saveButton = QPushButton(self) self.saveButton.setObjectName("saveButton") self.saveButton.clicked.connect(self.on_saveButton_clicked) self.saveButton.setText(self._translate("&Save")) self.saveButton.setShortcut("Ctrl+S") self.saveButton.setToolTip('Save the changes to the file (Ctrl+S)') self.saveButton.setFlat(True) self.horizontalLayout.addWidget(self.saveButton) return self.buttons def keyPressEvent(self, event): ''' Enable the shortcats for search and replace ''' if event.key() == Qt.Key_Escape: self.reject() elif event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_F: if self.tabWidget.currentWidget().hasFocus(): if not self.searchButton.isChecked(): self.searchButton.setChecked(True) else: self.on_toggled_find(True) else: self.searchButton.setChecked(not self.searchButton.isChecked()) elif event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_R: if self.tabWidget.currentWidget().hasFocus(): if not self.replaceButton.isChecked(): self.replaceButton.setChecked(True) else: self.on_toggled_replace(True) else: self.replaceButton.setChecked(not self.replaceButton.isChecked()) else: event.accept() QMainWindow.keyPressEvent(self, event) def _translate(self, text): if hasattr(QApplication, "UnicodeUTF8"): return QApplication.translate("Editor", text, None, QApplication.UnicodeUTF8) else: return QApplication.translate("Editor", text, None) def readSettings(self): if nm.settings().store_geometry: settings = nm.settings().qsettings(nm.settings().CFG_GUI_FILE) settings.beginGroup("editor") maximized = settings.value("maximized", 'false') == 'true' if maximized: self.showMaximized() else: self.resize(settings.value("size", QSize(800, 640))) self.move(settings.value("pos", QPoint(0, 0))) try: self.restoreState(settings.value("window_state")) except: import traceback print traceback.format_exc() settings.endGroup() def storeSetting(self): if nm.settings().store_geometry: settings = nm.settings().qsettings(nm.settings().CFG_GUI_FILE) settings.beginGroup("editor") settings.setValue("size", self.size()) settings.setValue("pos", self.pos()) settings.setValue("maximized", self.isMaximized()) settings.setValue("window_state", self.saveState()) settings.endGroup() def on_load_request(self, filename, search_text=''): ''' Loads a file in a new tab or focus the tab, if the file is already open. @param filename: the path to file @type filename: C{str} @param search_text: if not empty, searches in new document for first occurrence of the given text @type search_text: C{str} (Default: C{Empty String}) ''' if not filename: return self.tabWidget.setUpdatesEnabled(False) try: if filename not in self.files: tab_name = self.__getTabName(filename) editor = TextEdit(filename, self.tabWidget) linenumber_editor = LineNumberWidget(editor) tab_index = self.tabWidget.addTab(linenumber_editor, tab_name) self.files.append(filename) editor.setCurrentPath(os.path.basename(filename)) editor.load_request_signal.connect(self.on_load_request) editor.document().modificationChanged.connect(self.on_editor_modificationChanged) editor.cursorPositionChanged.connect(self.on_editor_positionChanged) editor.setFocus(Qt.OtherFocusReason) # editor.textChanged.connect(self.on_text_changed) editor.undoAvailable.connect(self.on_text_changed) self.tabWidget.setCurrentIndex(tab_index) # self.find_dialog.set_search_path(filename) else: for i in range(self.tabWidget.count()): if self.tabWidget.widget(i).filename == filename: self.tabWidget.setCurrentIndex(i) break except: import traceback rospy.logwarn("Error while open %s: %s", filename, traceback.format_exc(1)) self.tabWidget.setUpdatesEnabled(True) if search_text: try: self._search_thread.stop() self._search_thread = None except: pass self._search_thread = TextSearchThread(search_text, filename, path_text=self.tabWidget.widget(0).document().toPlainText(), recursive=True) self._search_thread.search_result_signal.connect(self.on_search_result_on_open) self._search_thread.start() def on_text_changed(self, value=""): if self.tabWidget.currentWidget().hasFocus(): self.find_dialog.file_changed(self.tabWidget.currentWidget().filename) def on_close_tab(self, tab_index): ''' Signal handling to close single tabs. @param tab_index: tab index to close @type tab_index: C{int} ''' try: doremove = True w = self.tabWidget.widget(tab_index) if w.document().isModified(): name = self.__getTabName(w.filename) result = QMessageBox.question(self, "Unsaved Changes", '\n\n'.join(["Save the file before closing?", name]), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if result == QMessageBox.Yes: self.tabWidget.currentWidget().save() elif result == QMessageBox.No: pass else: doremove = False if doremove: # remove the indexed files if w.filename in self.files: self.files.remove(w.filename) # close tab self.tabWidget.removeTab(tab_index) # close editor, if no tabs are open if not self.tabWidget.count(): self.close() except: import traceback rospy.logwarn("Error while close tab %s: %s", str(tab_index), traceback.format_exc(1)) def reject(self): if self.find_dialog.isVisible(): self.searchButton.setChecked(not self.searchButton.isChecked()) else: self.close() def closeEvent(self, event): ''' Test the open files for changes and save this if needed. ''' changed = [] # get the names of all changed files for i in range(self.tabWidget.count()): w = self.tabWidget.widget(i) if w.document().isModified(): changed.append(self.__getTabName(w.filename)) if changed: # ask the user for save changes if self.isHidden(): buttons = QMessageBox.Yes | QMessageBox.No else: buttons = QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel result = QMessageBox.question(self, "Unsaved Changes", '\n\n'.join(["Save the file before closing?", '\n'.join(changed)]), buttons) if result == QMessageBox.Yes: for i in range(self.tabWidget.count()): w = self.tabWidget.widget(i).save() event.accept() elif result == QMessageBox.No: event.accept() else: event.ignore() else: event.accept() if event.isAccepted(): self.storeSetting() self.finished_signal.emit(self.init_filenames) def on_editor_modificationChanged(self, value=None): ''' If the content was changed, a '*' will be shown in the tab name. ''' tab_name = self.__getTabName(self.tabWidget.currentWidget().filename) if (self.tabWidget.currentWidget().document().isModified()) or not QFileInfo(self.tabWidget.currentWidget().filename).exists(): tab_name = ''.join(['*', tab_name]) self.tabWidget.setTabText(self.tabWidget.currentIndex(), tab_name) def on_editor_positionChanged(self): ''' Shows the number of the line and column in a label. ''' cursor = self.tabWidget.currentWidget().textCursor() self.pos_label.setText(':%s:%s #%s' % (cursor.blockNumber() + 1, cursor.columnNumber(), cursor.position())) def __getTabName(self, lfile): base = os.path.basename(lfile).replace('.launch', '') (package, _) = package_name(os.path.dirname(lfile)) return '%s [%s]' % (base, package) ############################################################################## # HANDLER for buttons ############################################################################## def on_saveButton_clicked(self): ''' Saves the current document. This method is called if the C{save button} was clicked. ''' saved, errors, msg = self.tabWidget.currentWidget().save(True) if errors: QMessageBox.critical(self, "Error", msg) self.tabWidget.setTabIcon(self.tabWidget.currentIndex(), self._error_icon) self.tabWidget.setTabToolTip(self.tabWidget.currentIndex(), msg) elif saved: self.tabWidget.setTabIcon(self.tabWidget.currentIndex(), self._empty_icon) self.tabWidget.setTabToolTip(self.tabWidget.currentIndex(), '') def on_shortcut_find(self): pass def on_toggled_find(self, value): ''' Shows the search frame ''' if value: self.find_dialog.enable() else: self.replaceButton.setChecked(False) self.find_dialog.setVisible(False) self.tabWidget.currentWidget().setFocus() def on_toggled_replace(self, value): ''' Shows the replace lineedit in the search frame ''' if value: self.searchButton.setChecked(True) self.find_dialog.set_replace_visible(value) def on_shortcut_goto(self): ''' Opens a C{goto} dialog. ''' value = 1 ok = False try: value, ok = QInputDialog.getInt(self, "Goto", self.tr("Line number:"), QLineEdit.Normal, minValue=1, step=1) except: value, ok = QInputDialog.getInt(self, "Goto", self.tr("Line number:"), QLineEdit.Normal, min=1, step=1) if ok: if value > self.tabWidget.currentWidget().document().blockCount(): value = self.tabWidget.currentWidget().document().blockCount() curpos = self.tabWidget.currentWidget().textCursor().blockNumber() + 1 while curpos != value: mov = QTextCursor.NextBlock if curpos < value else QTextCursor.PreviousBlock self.tabWidget.currentWidget().moveCursor(mov) curpos = self.tabWidget.currentWidget().textCursor().blockNumber() + 1 self.tabWidget.currentWidget().setFocus(Qt.ActiveWindowFocusReason) ############################################################################## # SLOTS for search dialog ############################################################################## def on_search_result(self, search_text, found, path, index): ''' A slot to handle a found text. It goes to the position in the text and select the searched text. On new file it will be open. :param search_text: the searched text :type search_text: str :param found: the text was found or not :type found: bool :param path: the path of the file the text was found :type path: str :param index: the position in the text :type index: int ''' if found: if self.tabWidget.currentWidget().filename != path: focus_widget = QApplication.focusWidget() self.on_load_request(path) focus_widget.setFocus() cursor = self.tabWidget.currentWidget().textCursor() cursor.setPosition(index, QTextCursor.MoveAnchor) cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor, len(search_text)) self.tabWidget.currentWidget().setTextCursor(cursor) def on_search_result_on_open(self, search_text, found, path, index): ''' Like on_search_result, but skips the text in comments. ''' if found: if self.tabWidget.currentWidget().filename != path: focus_widget = QApplication.focusWidget() self.on_load_request(path) focus_widget.setFocus() comment_start = self.tabWidget.currentWidget().document().find('<!--', index, QTextDocument.FindBackward) if not comment_start.isNull(): comment_end = self.tabWidget.currentWidget().document().find('-->', comment_start) if not comment_end.isNull() and comment_end.position() > index + len(search_text): # commented -> retrun return self.on_search_result(search_text, found, path, index) def on_replace(self, search_text, path, index, replaced_text): ''' A slot to handle a text replacement of the TextSearchFrame. :param search_text: the searched text :type search_text: str :param path: the path of the file the text was found :type path: str :param index: the position in the text :type index: int :param replaced_text: the new text :type replaced_text: str ''' cursor = self.tabWidget.currentWidget().textCursor() if cursor.selectedText() == search_text: cursor.insertText(replaced_text) ############################################################################## # LAUNCH TAG insertion ############################################################################## def _create_tag_button(self, parent=None): btn = QPushButton(parent) btn.setObjectName("tagButton") btn.setText(self._translate("Add &tag")) btn.setShortcut("Ctrl+T") btn.setToolTip('Adds a ROS launch tag to launch file (Ctrl+T)') btn.setMenu(self._create_tag_menu(btn)) btn.setFlat(True) return btn def _create_tag_menu(self, parent=None): # creates a tag menu tag_menu = QMenu("ROS Tags", parent) # group tag add_group_tag_action = QAction("<group>", self, statusTip="", triggered=self._on_add_group_tag) add_group_tag_action.setShortcuts(QKeySequence("Ctrl+Shift+g")) tag_menu.addAction(add_group_tag_action) # node tag add_node_tag_action = QAction("<node>", self, statusTip="", triggered=self._on_add_node_tag) add_node_tag_action.setShortcuts(QKeySequence("Ctrl+Shift+n")) tag_menu.addAction(add_node_tag_action) # node tag with all attributes add_node_tag_all_action = QAction("<node all>", self, statusTip="", triggered=self._on_add_node_tag_all) tag_menu.addAction(add_node_tag_all_action) # include tag with all attributes add_include_tag_all_action = QAction("<include>", self, statusTip="", triggered=self._on_add_include_tag_all) add_include_tag_all_action.setShortcuts(QKeySequence("Ctrl+Shift+i")) tag_menu.addAction(add_include_tag_all_action) # remap add_remap_tag_action = QAction("<remap>", self, statusTip="", triggered=self._on_add_remap_tag) add_remap_tag_action.setShortcuts(QKeySequence("Ctrl+Shift+r")) tag_menu.addAction(add_remap_tag_action) # env tag add_env_tag_action = QAction("<env>", self, statusTip="", triggered=self._on_add_env_tag) tag_menu.addAction(add_env_tag_action) # param tag add_param_tag_action = QAction("<param>", self, statusTip="", triggered=self._on_add_param_tag) add_param_tag_action.setShortcuts(QKeySequence("Ctrl+Shift+p")) tag_menu.addAction(add_param_tag_action) # param capability group tag add_param_cap_group_tag_action = QAction("<param capability group>", self, statusTip="", triggered=self._on_add_param_cap_group_tag) add_param_cap_group_tag_action.setShortcuts(QKeySequence("Ctrl+Alt+p")) tag_menu.addAction(add_param_cap_group_tag_action) # param tag with all attributes add_param_tag_all_action = QAction("<param all>", self, statusTip="", triggered=self._on_add_param_tag_all) tag_menu.addAction(add_param_tag_all_action) # rosparam tag with all attributes add_rosparam_tag_all_action = QAction("<rosparam>", self, statusTip="", triggered=self._on_add_rosparam_tag_all) tag_menu.addAction(add_rosparam_tag_all_action) # arg tag with default definition add_arg_tag_default_action = QAction("<arg default>", self, statusTip="", triggered=self._on_add_arg_tag_default) add_arg_tag_default_action.setShortcuts(QKeySequence("Ctrl+Shift+a")) tag_menu.addAction(add_arg_tag_default_action) # arg tag with value definition add_arg_tag_value_action = QAction("<arg value>", self, statusTip="", triggered=self._on_add_arg_tag_value) add_arg_tag_value_action.setShortcuts(QKeySequence("Ctrl+Alt+a")) tag_menu.addAction(add_arg_tag_value_action) # test tag add_test_tag_action = QAction("<test>", self, statusTip="", triggered=self._on_add_test_tag) add_test_tag_action.setShortcuts(QKeySequence("Ctrl+Alt+t")) tag_menu.addAction(add_test_tag_action) # test tag with all attributes add_test_tag_all_action = QAction("<test all>", self, statusTip="", triggered=self._on_add_test_tag_all) tag_menu.addAction(add_test_tag_all_action) return tag_menu def _insert_text(self, text): cursor = self.tabWidget.currentWidget().textCursor() if not cursor.isNull(): col = cursor.columnNumber() spaces = ''.join([' ' for _ in range(col)]) cursor.insertText(text.replace('\n', '\n%s' % spaces)) self.tabWidget.currentWidget().setFocus(Qt.OtherFocusReason) def _on_add_group_tag(self): self._insert_text('<group ns="namespace" clear_params="true|false">\n' '</group>') def _on_add_node_tag(self): dia = PackageDialog() if dia.exec_(): self._insert_text('<node name="%s" pkg="%s" type="%s">\n' '</node>' % (dia.binary, dia.package, dia.binary)) def _on_add_node_tag_all(self): dia = PackageDialog() if dia.exec_(): self._insert_text('<node name="%s" pkg="%s" type="%s"\n' ' args="arg1" machine="machine-name"\n' ' respawn="true" required="true"\n' ' ns="foo" clear_params="true|false"\n' ' output="log|screen" cwd="ROS_HOME|node"\n' ' launch-prefix="prefix arguments">\n' '</node>' % (dia.binary, dia.package, dia.binary)) def _on_add_include_tag_all(self): self._insert_text('<include file="$(find pkg-name)/path/filename.xml"\n' ' ns="foo" clear_params="true|false">\n' '</include>') def _on_add_remap_tag(self): self._insert_text('<remap from="original" to="new"/>') def _on_add_env_tag(self): self._insert_text('<env name="variable" value="value"/>') def _on_add_param_tag(self): self._insert_text('<param name="ns_name" value="value" />') def _on_add_param_cap_group_tag(self): self._insert_text('<param name="capability_group" value="demo" />') def _on_add_param_tag_all(self): self._insert_text('<param name="ns_name" value="value"\n' ' type="str|int|double|bool"\n' ' textfile="$(find pkg-name)/path/file.txt"\n' ' binfile="$(find pkg-name)/path/file"\n' ' command="$(find pkg-name)/exe \'$(find pkg-name)/arg.txt\'">\n' '</param>') def _on_add_rosparam_tag_all(self): self._insert_text('<rosparam param="param-name"\n' ' file="$(find pkg-name)/path/foo.yaml"\n' ' command="load|dump|delete"\n' ' ns="namespace">\n' '</rosparam>') def _on_add_arg_tag_default(self): self._insert_text('<arg name="foo" default="1" />') def _on_add_arg_tag_value(self): self._insert_text('<arg name="foo" value="bar" />') def _on_add_test_tag(self): dia = PackageDialog() if dia.exec_(): self._insert_text('<test name="%s" pkg="%s" type="%s" test-name="test_%s">\n' '</test>' % (dia.binary, dia.package, dia.binary, dia.binary)) def _on_add_test_tag_all(self): dia = PackageDialog() if dia.exec_(): self._insert_text('<test name="%s" pkg="%s" type="%s" test-name="test_%s">\n' ' args="arg1" time-limit="60.0"\n' ' ns="foo" clear_params="true|false"\n' ' cwd="ROS_HOME|node" retry="0"\n' ' launch-prefix="prefix arguments">\n' '</test>' % (dia.binary, dia.package, dia.binary, dia.binary))
class LevelSelectorPlugin(Plugin): def __init__(self, context): super(LevelSelectorPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('LevelSelectorPlugin') # Create QWidget self._widget = QWidget() # self._widget.setFont(QFont("Times", 15, QFont.Bold)) self._button_layout = QVBoxLayout(self._widget) self.buttons = [] self.text_label = QLabel("Waiting for MultiLevelMapData...", self._widget) self._button_layout.addWidget(self.text_label) self._widget.setObjectName('LevelSelectorPluginUI') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) self.connect(self._widget, SIGNAL("update_buttons"), self.update_buttons) self.connect(self._widget, SIGNAL("update_button_status"), self.update_button_status) # Subcribe to the multi level map data to get information about all the maps. self.multimap_subscriber = rospy.Subscriber("map_metadata", MultiLevelMapData, self.process_multimap) self.levels = [] self.current_level = None # Subscribe to the current level we are on. self.status_subscriber = None # Create a service proxy to change the current level. self.level_selector_proxy = rospy.ServiceProxy("level_mux/change_current_level", ChangeCurrentLevel) self.level_selector_proxy.wait_for_service() def process_multimap(self, msg): self.levels = msg.levels self._widget.emit(SIGNAL("update_buttons")) def update_buttons(self): self.clean() for index, level in enumerate(self.levels): self.text_label.setText("Choose Level: ") button = QPushButton(level.level_id, self._widget) button.clicked[bool].connect(self.handle_button) button.setCheckable(True) self._button_layout.addWidget(button) self.buttons.append(button) # Subscribe to the current level we are on. if self.status_subscriber is None: self.status_subscriber = rospy.Subscriber("level_mux/current_level", LevelMetaData, self.process_level_status) def update_button_status(self): for index, level in enumerate(self.levels): if self.current_level == level.level_id: self.buttons[index].setChecked(True) else: self.buttons[index].setChecked(False) def process_level_status(self, msg): level_found = False for level in self.levels: if msg.level_id == level.level_id: self.current_level = level.level_id level_found = True break if not level_found: self.current_level = None self._widget.emit(SIGNAL("update_button_status")) def handle_button(self): source = self.sender() if source.text() == self.current_level: source.setChecked(True) return # Construct a identity pose. The level selector cannot be used to choose the initialpose, as it does not have # the interface for specifying the position. The position should be specified via rviz. origin_pose = PoseWithCovarianceStamped() origin_pose.header.frame_id = frameIdFromLevelId(source.text()) origin_pose.pose.pose.orientation.w = 1 # Makes the origin quaternion valid. origin_pose.pose.covariance[0] = 1.0 origin_pose.pose.covariance[7] = 1.0 origin_pose.pose.covariance[14] = 1.0 origin_pose.pose.covariance[21] = 1.0 origin_pose.pose.covariance[28] = 1.0 origin_pose.pose.covariance[35] = 1.0 # Don't actually publish the initial pose via the level selector. It doesn't know any better. self.level_selector_proxy(source.text(), False, origin_pose) def clean(self): while self._button_layout.count(): item = self._button_layout.takeAt(0) item.widget().deleteLater() def save_settings(self, plugin_settings, instance_settings): pass def restore_settings(self, plugin_settings, instance_settings): pass