def motor_controller(self): ''' Sets up the GUI in the middle of the Screen to control the motors. Uses self._motorValues to determine which motors are present. ''' i = 0 for k, v in sorted(self._currentGoals.items()): group = QGroupBox() slider = QSlider(Qt.Horizontal) slider.setTickInterval(1) slider.setMinimum(-181) slider.setMaximum(181) slider.valueChanged.connect(self.slider_update) self._sliders[k] = slider textfield = QLineEdit() textfield.setText('0') textfield.textEdited.connect(self.textfield_update) self._textFields[k] = textfield label = QLabel() label.setText(k) layout = QVBoxLayout() layout.addWidget(label) layout.addWidget(self._sliders[k]) layout.addWidget(self._textFields[k]) group.setLayout(layout) self._widget.motorControlLayout.addWidget(group, i / 5, i % 5) i = i+1
class BoxGroup(GroupWidget): def __init__(self, updater, config, nodename): super(BoxGroup, self).__init__(updater, config, nodename) self.box = QGroupBox(self.param_name) self.box.setLayout(self.grid) def display(self, grid): grid.addRow(self.box)
class BoxGroup(GroupWidget): def __init__(self, updater, config): super(BoxGroup, self).__init__(updater, config) self.box = QGroupBox(self.name) self.box.setLayout(self.grid) def display(self, grid, row): grid.addWidget(self.box, row, 0, 1, -1)
def create_subgait(self, name, subgait, version_selection): subgait_group_box = QGroupBox() subgait_group_box.setLayout(QGridLayout()) subgait_group_box.setObjectName('Subgait') subgait_group_box.setTitle(name) try: version_name = version_selection[name] except TypeError: version_name = None except KeyError: version_name = None dropdown = self.create_dropdown(subgait, version_name) subgait_group_box.layout().addWidget(dropdown, 0, 0) return subgait_group_box
def beginGroup(self,obj): parent,layout = self.__get_immediate_parent() panel = QGroupBox(obj.name,parent) if obj.layout == "grid": l = QGridLayout() elif obj.layout == "vertical": l = QVBoxLayout() else: l = QHBoxLayout() self.__increase_nesting_level(panel, l)
def add_widgets(self): """ Add groups of widgets to _main_widget. Supports group labels. This method can be reimplemented in order to customize appearances. """ widgets = self.get_widgets() self._widgets = [] # stores widgets which may need to be shut down when done for group in widgets: # Check for group label if isinstance(group[0], str): grouplabel, v = group box = QGroupBox(grouplabel) box.setContentsMargins(0, 18, 0, 0) # LTRB # Apply the center-label directive only for single-icon groups if len(group[1]) == 1: box.setAlignment(Qt.AlignHCenter) else: box = QGroupBox() box.setContentsMargins(0, 0, 0, 0) # LTRB v = group # Add widgets to QGroupBox layout = QHBoxLayout() layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) # LTRB for i in v: try: try: i.setIconSize(self.max_icon_size) # without this, icons are tiny except AttributeError as e: # triggers with battery which uses a QLabel instead of a QToolButton-based widget pass layout.addWidget(i) self._widgets.append(i) except: raise Exception("All widgets must be a subclass of QWidget!") layout.activate() box.setLayout(layout) self._main_widget.addWidget(box) self._main_widget.addSeparator()
def add_config(self, title, choices, single_choice=True): ''' create a UI element for selecting options for one variation and put it in a scrollArea ''' scroll = QScrollArea() group_box = QGroupBox(title) group_box.setFlat(True) layout = QVBoxLayout() if len(choices) > 5 and single_choice: combo_box = QComboBox(group_box) for obj in choices: combo_box.addItem(obj) layout.addWidget(combo_box) else: for obj in choices: if single_choice: layout.addWidget(QRadioButton(obj, group_box)) else: layout.addWidget(QCheckBox(obj, group_box)) layout.addStretch(1) group_box.setLayout(layout) scroll.setWidget(group_box) scroll.setWidgetResizable(True) return group_box, scroll
def __init__(self, title, items, parent): super(ListDialog, self).__init__(parent) self._layout = QVBoxLayout() self._view_box = QGroupBox("Optional topics") self._view_box_layout = QVBoxLayout(self._view_box) self._list_widget = QListWidget() self._view_box_layout.addWidget(self._list_widget) self._button_box = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Close) self._button_box.accepted.connect(self.save) self._button_box.rejected.connect(self.reject) self.setWindowTitle(title) self.create_list_widget(items) self._layout.addWidget(self._view_box) self._layout.addWidget(self._button_box) self.setLayout(self._layout) # createConnections self._list_widget.itemChanged.connect(self.highlight_checked) self.selected_items = []
def setupButtons(self, yaml_file): """ Parse yaml file and setup Buttons. Format of the yaml file should be: - name: 'button name' (required) image: 'path to image for icon' (optional) image_size: 'width and height of icon' (optional) service: 'service' (required) column: 'column index' (optional, defaults to 0) """ self.buttons = [] with open(yaml_file) as f: yaml_data = yaml.load(f) # lookup colum direction direction = 'vertical' for d in yaml_data: if d.has_key('direction'): if d['direction'] == 'horizontal': direction = 'horizontal' else: # d['direction'] == 'vertical': direction = 'vertical' yaml_data.remove(d) break # lookup column num column_indices = [d['column'] for d in yaml_data] max_column_index = max(*column_indices) if direction == 'vertical': self.layout = QHBoxLayout() self.layout_boxes = [ QVBoxLayout() for i in range(max_column_index + 1) ] else: # direction == 'horizontal' self.layout = QVBoxLayout() self.layout_boxes = [ QHBoxLayout() for i in range(max_column_index + 1) ] self.button_groups = [ QGroupBox() for i in range(max_column_index + 1) ] for button_data in yaml_data: # check if all the field is available if not button_data.has_key("name"): self.showError("name field is missed in yaml") raise Exception("name field is missed in yaml") if not button_data.has_key("service"): self.showError("service field is missed in yaml") raise Exception("service field is missed in yaml") if self.button_type == "push": button = QToolButton() else: # self.button_type == "radio": button = QRadioButton() button.setSizePolicy( QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)) if button_data.has_key("image"): image_file = get_filename( button_data["image"])[len("file://"):] if os.path.exists(image_file): icon = QtGui.QIcon(image_file) button.setIcon(icon) if button_data.has_key("image_size"): button.setIconSize( QSize(button_data["image_size"][0], button_data["image_size"][1])) else: button.setIconSize(QSize(100, 100)) if button_data.has_key("name"): name = button_data['name'] button.setText(name) if button_data.has_key('service_type'): if button_data['service_type'] == 'Trigger': service_type = Trigger elif button_data['service_type'] == 'Empty': service_type = Empty elif button_data['service_type'] == 'SetBool': service_type = SetBool else: raise Exception("Unsupported service type: {}".format( button_data['service_type'])) else: service_type = Empty if service_type == SetBool: button.setCheckable(True) button.clicked.connect( self.buttonCallback(button_data['service'], service_type, button)) if self.button_type == "push": button.setToolButtonStyle( QtCore.Qt.ToolButtonTextUnderIcon) if ((self.button_type == "radio" or service_type == SetBool) and ("default_value" in button_data and button_data['default_value'])): button.setChecked(True) self.layout_boxes[button_data['column']].addWidget(button) self.buttons.append(button) for i in range(len(self.button_groups)): self.button_groups[i].setLayout(self.layout_boxes[i]) for group in self.button_groups: self.layout.addWidget(group) self.setLayout(self.layout)
def add_widgets(self): """ Add groups of widgets to _main_widget. Supports group labels. This method can be reimplemented in order to customize appearances. """ widgets = self.get_widgets() self._widgets = [ ] # stores widgets which may need to be shut down when done for group in widgets: # Check for group label if isinstance(group[0], str): grouplabel, v = group box = QGroupBox(grouplabel) box.setContentsMargins(0, 18, 0, 0) # LTRB # Apply the center-label directive only for single-icon groups if len(group[1]) == 1: box.setAlignment(Qt.AlignHCenter) else: box = QGroupBox() box.setContentsMargins(0, 0, 0, 0) # LTRB v = group # Add widgets to QGroupBox layout = QHBoxLayout() layout.setSpacing(0) layout.setContentsMargins(0, 0, 0, 0) # LTRB for i in v: try: try: i.setIconSize( self.max_icon_size) # without this, icons are tiny except AttributeError as e: # triggers with battery which uses a QLabel instead of a QToolButton-based widget pass layout.addWidget(i) self._widgets.append(i) except: raise Exception( "All widgets must be a subclass of QWidget!") layout.activate() box.setLayout(layout) self._main_widget.addWidget(box) self._main_widget.addSeparator()
class BenchmarkConfig(object): def __init__(self, config, config_path, benchmark_name, benchmark_result_type): self.config = config self.config_path = config_path self.benchmark_name = benchmark_name self.result_type = benchmark_result_type self.variation_widgets = {} self.result_widgets = {} self.bagfile_name = None self.notes_widget = None def setup(self, config_layout, results_layout, config_locked): ''' set up the layout for selecting options from the different benchmark variations ''' config_group_box_layout = QHBoxLayout() self.config_group_box = QGroupBox('Configuration') self.config_group_box.setCheckable(True) if (config_locked): self.config_group_box.setChecked(False) variations = self.config['variations'].keys() for var in variations: single_choice = True if var in self.config['multiple choice variation']: single_choice = False if isinstance(self.config['variations'][var], list): self.variation_widgets[var], scroll = self.add_config( var, self.config['variations'][var], single_choice=single_choice) config_group_box_layout.addWidget(scroll) else: path = os.path.join(self.config_path, self.config['variations'][var]) if os.path.exists(path): with open(path) as f: options = f.readlines() options = [x.strip() for x in options] self.variation_widgets[var], scroll = self.add_config( var, options, single_choice=single_choice) config_group_box_layout.addWidget(scroll) self.config['variations'][var] = options else: QMessageBox.critical(None, "Error", "File %s does not exist" % path) self.config_group_box.setLayout(config_group_box_layout) config_layout.addWidget(self.config_group_box) results_group_box = QGroupBox('Results') results_group_box_layout = QHBoxLayout() results = self.config['results'].keys() for res in results: single_choice = True if var in self.config['multiple choice result']: single_choice = False if isinstance(self.config['results'][res], list): self.result_widgets[res], scroll = self.add_config( res, self.config['results'][res], single_choice=single_choice) results_group_box_layout.addWidget(scroll) else: if self.config['results'][res] == 'text_field': widget = QWidget() text_field = QLineEdit() text_field.setReadOnly(True) txtlayout = QHBoxLayout() txtlayout.addWidget(QLabel(res)) txtlayout.addWidget(text_field) widget.setLayout(txtlayout) self.result_widgets[res] = text_field results_group_box_layout.addWidget(widget) results_group_box.setLayout(results_group_box_layout) results_layout.addWidget(results_group_box) self.notes_widget = QPlainTextEdit() self.notes_widget.setMaximumHeight(100) self.notes_widget.setPlaceholderText('Enter notes about the result...') results_layout.addWidget(self.notes_widget) def add_config(self, title, choices, single_choice=True): ''' create a UI element for selecting options for one variation and put it in a scrollArea ''' scroll = QScrollArea() group_box = QGroupBox(title) group_box.setFlat(True) layout = QVBoxLayout() if len(choices) > 5 and single_choice: combo_box = QComboBox(group_box) for obj in choices: combo_box.addItem(obj) layout.addWidget(combo_box) else: for obj in choices: if single_choice: layout.addWidget(QRadioButton(obj, group_box)) else: layout.addWidget(QCheckBox(obj, group_box)) layout.addStretch(1) group_box.setLayout(layout) scroll.setWidget(group_box) scroll.setWidgetResizable(True) return group_box, scroll def get_current_selections(self): ''' read current selections from the config UI elements and return it as a dictionary ''' variations = self.config['variations'].keys() trial_config = {} for var in variations: widget = self.variation_widgets[var] selections = [] for child in widget.children(): if isinstance(child, QRadioButton) or isinstance( child, QCheckBox): if child.isChecked(): selections.append(child.text()) elif isinstance(child, QComboBox): selections.append(child.currentText()) trial_config[var] = selections return trial_config def apply_selections(self, trial_config): ''' apply selections specified in trial_config to config UI elements ''' variations = self.config['variations'].keys() for var in variations: widget = self.variation_widgets[var] selections = trial_config[var] if len(selections) == 0: return for child in widget.children(): if isinstance(child, QRadioButton) or isinstance( child, QCheckBox): if child.text() in selections: child.setChecked(True) else: child.setChecked(False) elif isinstance(child, QComboBox): child.setCurrentText(selections[0]) def clear_selections(self): ''' remove all selections in config UI elements (except radio buttons since they cannot be unselected) ''' variations = self.config['variations'].keys() for var in variations: widget = self.variation_widgets[var] for child in widget.children(): if isinstance(child, QRadioButton) or isinstance( child, QCheckBox): child.setChecked(False) elif isinstance(child, QComboBox): child.setCurrentIndex(0) def generate(self): ''' Generate a set of selections for all config elements ''' trial_config = {} variations = self.config['variations'].keys() for var in variations: single_choice = True if var in self.config['multiple choice variation']: single_choice = False selected_indices = [] if single_choice: choices = list(range(len(self.config['variations'][var]))) probabilities = None if var in self.config['selection likelihood'].keys(): probabilities = self.config['selection likelihood'][var] choice = np.random.choice(choices, p=probabilities) selected_indices.append(choice) else: num_choices = len(self.config['variations'][var]) # TODO: should this be configurable? min_selections = 2 max_selections = 5 num_selections = random.randint(min_selections, max_selections) for idx in range(num_selections): choice = random.randrange(0, num_choices) selected_indices.append(choice) selected_items = np.array( self.config['variations'][var])[selected_indices].tolist() trial_config[var] = selected_items return trial_config def show_results(self, msg, timeout, stopped): pass def clear_results(self): ''' clear results elements ''' self.bagfile_name = None results = self.config['results'].keys() for res in results: if isinstance(self.config['results'][res], list): single_choice = True if var in self.config['multiple choice result']: single_choice = False if not single_choice: widget = self.result_widgets[res] for child in widget.children(): if isinstance(child, QRadioButton) or isinstance( child, QCheckBox): child.setChecked(False) elif isinstance(child, QComboBox): child.setCurrentIndex(0) else: self.result_widgets[res].setText('') self.notes_widget.clear() def get_trial_result_dict(self, msg, current_trial_name, current_team_name, timeout, stopped, elapsed_time): ''' return dictionary with all result fields for this benchmark ''' results = {} results['trial_id'] = current_trial_name results['team_name'] = current_team_name results['bagfile'] = self.bagfile_name results['duration'] = elapsed_time results['timeout'] = timeout results['stopped'] = stopped results['config'] = self.get_current_selections() results['notes'] = self.notes_widget.toPlainText() if not stopped and not timeout: results['results'] = self.get_result_dict_from_msg(msg) else: results['results'] = {} return results def get_result_dict_from_msg(self, msg): ''' Return benchmark-specific results in the form of a dictionary Must be overridden by subclasses. ''' pass def get_task_info_for_robot(self): ''' return config information which is required for the robot to perform the task e.g. object to be detected, grasp pose, navigation poses etc. ''' return {} def get_timeout(self): return self.config["timeout"] def set_bagfile_name(self, name): self.bagfile_name = name def get_bagfile_name(self): return self.bagfile_name def lock_config(self): self.config_group_box.setChecked(False) def unlock_config(self): self.config_group_box.setChecked(True)
def __init__(self, updater, config, nodename): super(BoxGroup, self).__init__(updater, config, nodename) self.box = QGroupBox(self.param_name) self.box.setLayout(self.grid)
def create_gait(self, name, gait, selections): gait_group_box = QGroupBox() gait_group_box.setObjectName('Gait') gait_group_box.setLayout(QHBoxLayout()) gait_group_box.setTitle(name) image = QLabel() image.setStyleSheet( 'background: url(' + gait['image'] + ') no-repeat center center 100px 100px;') image.setFixedSize(64, 80) gait_group_box.layout().addWidget(image) for subgait_name, subgait in gait['subgaits'].iteritems(): subgait_group_box = self.create_subgait(subgait_name, subgait, selections) gait_group_box.layout().addWidget(subgait_group_box) return gait_group_box
def setup(self, config_layout, results_layout, config_locked): ''' set up the layout for selecting options from the different benchmark variations ''' config_group_box_layout = QHBoxLayout() self.config_group_box = QGroupBox('Configuration') self.config_group_box.setCheckable(True) if (config_locked): self.config_group_box.setChecked(False) variations = self.config['variations'].keys() for var in variations: single_choice = True if var in self.config['multiple choice variation']: single_choice = False if isinstance(self.config['variations'][var], list): self.variation_widgets[var], scroll = self.add_config( var, self.config['variations'][var], single_choice=single_choice) config_group_box_layout.addWidget(scroll) else: path = os.path.join(self.config_path, self.config['variations'][var]) if os.path.exists(path): with open(path) as f: options = f.readlines() options = [x.strip() for x in options] self.variation_widgets[var], scroll = self.add_config( var, options, single_choice=single_choice) config_group_box_layout.addWidget(scroll) self.config['variations'][var] = options else: QMessageBox.critical(None, "Error", "File %s does not exist" % path) self.config_group_box.setLayout(config_group_box_layout) config_layout.addWidget(self.config_group_box) results_group_box = QGroupBox('Results') results_group_box_layout = QHBoxLayout() results = self.config['results'].keys() for res in results: single_choice = True if var in self.config['multiple choice result']: single_choice = False if isinstance(self.config['results'][res], list): self.result_widgets[res], scroll = self.add_config( res, self.config['results'][res], single_choice=single_choice) results_group_box_layout.addWidget(scroll) else: if self.config['results'][res] == 'text_field': widget = QWidget() text_field = QLineEdit() text_field.setReadOnly(True) txtlayout = QHBoxLayout() txtlayout.addWidget(QLabel(res)) txtlayout.addWidget(text_field) widget.setLayout(txtlayout) self.result_widgets[res] = text_field results_group_box_layout.addWidget(widget) results_group_box.setLayout(results_group_box_layout) results_layout.addWidget(results_group_box) self.notes_widget = QPlainTextEdit() self.notes_widget.setMaximumHeight(100) self.notes_widget.setPlaceholderText('Enter notes about the result...') results_layout.addWidget(self.notes_widget)
def setup(self): layout = QGridLayout() # Sidebar self.benchmark_combo_box = QComboBox() for key in self.config['benchmarks'].keys(): self.benchmark_combo_box.addItem( self.config['benchmarks'][key]['name']) self.benchmark_combo_box.currentIndexChanged.connect( self._handle_benchmark_selected) self.benchmark_combo_box.setMaximumWidth(SIDEBAR_WIDTH) self.set_current_benchmark() self.team_combo_box = QComboBox() for key in self.config['teams']: self.team_combo_box.addItem(key) self.team_combo_box.setMaximumWidth(SIDEBAR_WIDTH) self.test_communication_button = QPushButton('Test communication') self.test_communication_button.clicked.connect(self._handle_test_comm) self.trial_list_widget = QListWidget() self.trial_list_widget.currentItemChanged.connect( self._handle_trial_change) self.trial_list_widget.setMaximumWidth(SIDEBAR_WIDTH) sidebar_layout = QVBoxLayout() sidebar_layout.addWidget(QLabel("Team")) sidebar_layout.addWidget(self.team_combo_box) sidebar_layout.addWidget(self.test_communication_button) sidebar_layout.addWidget(QLabel("Benchmark")) sidebar_layout.addWidget(self.benchmark_combo_box) sidebar_layout.addWidget(QLabel("Trial")) sidebar_layout.addWidget(self.trial_list_widget) self.generate_button = QPushButton('Generate') self.generate_button.clicked.connect(self._handle_generate) self.delete_button = QPushButton('Delete') self.delete_button.clicked.connect(self._handle_delete) self.save_trials_button = QPushButton('Save') self.save_trials_button.clicked.connect(self._handle_save_trial_config) self.lock_button = QPushButton('Lock') if self.config_locked: self.lock_button.setText('Unlock') self.lock_button.clicked.connect(self._handle_lock) sidebar_button_layout = QGridLayout() sidebar_button_layout.addWidget(self.generate_button, 0, 0) sidebar_button_layout.addWidget(self.delete_button, 0, 1) sidebar_button_layout.addWidget(self.save_trials_button, 1, 0) sidebar_button_layout.addWidget(self.lock_button, 1, 1) sidebar_layout.addLayout(sidebar_button_layout) layout.addLayout(sidebar_layout, 0, 0) # Status box self.status = QPlainTextEdit() self.status.setReadOnly(True) self.status.setMaximumHeight(200) # row 1, col 0, rowspan 1, colspan 2 layout.addWidget(self.status, 1, 0, 1, 2) # trial config and results trial_layout = QVBoxLayout() self.trial_config_layout = QHBoxLayout() self.trial_results_layout = QVBoxLayout() self.setup_trial_config() # benchmark trial controls benchmark_controls_group_box = QGroupBox('Controls') benchmark_controls_layout = QHBoxLayout() self.start_trial_button = QPushButton('Start') self.start_trial_button.clicked.connect(self._handle_start_trial) self.stop_trial_button = QPushButton('Stop') self.stop_trial_button.clicked.connect(self._handle_stop_trial) self.prev_trial_button = QPushButton('Previous') self.prev_trial_button.clicked.connect(self._handle_prev_trial) self.next_trial_button = QPushButton('Next') self.next_trial_button.clicked.connect(self._handle_next_trial) self.start_continuous_recording_button = QPushButton( 'Start continuous recording') self.start_continuous_recording_button.clicked.connect( self._handle_continuous_recording) self.timer_field = QLabel() font = QFont("Arial", 20, QFont.Bold) self.timer_field.setFont(font) self.timer_field.setAutoFillBackground(True) benchmark_controls_layout.addWidget(self.start_trial_button) benchmark_controls_layout.addWidget(self.stop_trial_button) benchmark_controls_layout.addWidget(self.prev_trial_button) benchmark_controls_layout.addWidget(self.next_trial_button) benchmark_controls_layout.addWidget( self.start_continuous_recording_button) benchmark_controls_layout.addWidget(self.timer_field) benchmark_controls_group_box.setLayout(benchmark_controls_layout) trial_layout.addLayout(self.trial_config_layout) trial_layout.addWidget(benchmark_controls_group_box) trial_layout.addLayout(self.trial_results_layout) self.save_results_button = QPushButton('Save results') self.save_results_button.clicked.connect(self._handle_save_result) trial_layout.addWidget(self.save_results_button) layout.addLayout(trial_layout, 0, 1) self.setLayout(layout) self.show() self.show_env_var('ROS_MASTER_URI') self.show_env_var('ROS_IP') self.show_env_var('ROS_HOSTNAME')