def __init__(self, parent): super(NodeSelection, self).__init__() self.parent_widget = parent self.selected_nodes = [] self.setWindowTitle("Select the nodes you want to record") self.resize(300, 300) self.area = QScrollArea(self) self.main_widget = QWidget(self.area) self.ok_button = QPushButton("Done", self) self.ok_button.clicked.connect(self.onButtonClicked) self.ok_button.setEnabled(False) self.main_vlayout = QVBoxLayout(self) self.main_vlayout.addWidget(self.area) self.main_vlayout.addWidget(self.ok_button) self.setLayout(self.main_vlayout) self.selection_vlayout = QVBoxLayout(self) self.node_list = rosnode.get_node_names() self.node_list.sort() for node in self.node_list: # add planner node by choosing agent number if "planner" not in node: self.addCheckBox(node) self.main_widget.setLayout(self.selection_vlayout) self.area.setWidget(self.main_widget) self.show()
def __init__(self): super(TopicSelection, self).__init__() master = rosgraph.Master('rqt_bag_recorder') self.setWindowTitle("Select the topics you want to record") self.resize(500, 700) self.topic_list = [] self.selected_topics = [] self.items_list = [] self.area = QScrollArea(self) self.main_widget = QWidget(self.area) self.ok_button = QPushButton("Record", self) self.ok_button.clicked.connect(self.onButtonClicked) self.ok_button.setEnabled(False) self.main_vlayout = QVBoxLayout(self) self.main_vlayout.addWidget(self.area) self.main_vlayout.addWidget(self.ok_button) self.setLayout(self.main_vlayout) self.selection_vlayout = QVBoxLayout(self) self.item_all = QCheckBox("All", self) self.item_all.stateChanged.connect(self.updateList) self.selection_vlayout.addWidget(self.item_all) topic_data_list = master.getPublishedTopics('') topic_data_list.sort() for topic, datatype in topic_data_list: self.addCheckBox(topic) self.main_widget.setLayout(self.selection_vlayout) self.area.setWidget(self.main_widget) self.show()
def __init__(self): super(PostProcMainWidget, self).__init__() # init the GUI components: self.bagWidget = BagWidget(self) self.bagFiles = self.bagWidget.getBagFiles() self.plotWidget = PlotWidget(self.bagFiles, self) self.__addPlotBtn = QPushButton("Add new Graph") self.__delPlotBtn = QPushButton("Delete Graph") self.__qualityBtn = QPushButton("Compute Data Quality") # connect signals to slots: self.__addPlotBtn.clicked.connect(self.openNewGraphDialog) self.__delPlotBtn.clicked.connect(self.openDelGraphDialog) self.__qualityBtn.clicked.connect(self.openQualityDialog) # setup the layout: layout = QGridLayout() # (rowIndex, rowStretch) layout.setRowStretch( 0, 0) # controls behavior when changing the window size # (widget, fromRow, fromColumn, rowSpan, columnSpan) layout.addWidget(self.bagWidget, 0, 0, 1, 3) layout.setRowStretch(1, 0) layout.addWidget(self.__addPlotBtn, 1, 0, 1, 1) layout.addWidget(self.__delPlotBtn, 1, 1, 1, 1) layout.addWidget(self.__qualityBtn, 1, 2, 1, 1) layout.setRowStretch(2, 1) layout.addWidget(self.plotWidget, 2, 0, 1, 3) self.setLayout(layout)
def __init__(self): QWidget.__init__(self) self._status = "unknown" self._layout = QGridLayout(self) self._widgets = dict() self.__logging_cb_signal.connect(self.logging_cb) self.__start_logging_signal.connect(self.start_logging) self.__stop_logging_signal.connect(self.stop_logging) self._add_widget("pid_label", QLabel("PID:", self)) self._add_widget("pid", QLineEdit(self)) self._widgets["pid"].setMaximumWidth(50) self._add_widget("label_status", QLabel(self)) self._widgets["label_status"].setText("Status: Unknown") self._widgets["label_status"].setTextFormat(QtCore.Qt.RichText) self._add_widget("button_start", QPushButton("START", self)) self._add_widget("button_stop", QPushButton("STOP", self)) self._widgets["button_start"].clicked.connect( self.__start_logging_signal.emit) self._widgets["button_stop"].clicked.connect( self.__stop_logging_signal.emit) self._widgets["label_warning"] = QLabel(self) self._layout.addWidget(self._widgets["label_warning"], 1, 0, 1, 2) self._widgets["label_warning"].setTextFormat(QtCore.Qt.RichText) rospy.Subscriber("/data_logger/status", String, self.__logging_cb_signal.emit) self._logging_start = rospy.ServiceProxy('/data_logger/start', DataLoggerStart) self._logging_stop = rospy.ServiceProxy('/data_logger/stop', DataLoggerStop)
def __init__(self, reconf, node_name): """ :type reconf: dynamic_reconfigure.client :type node_name: str """ group_desc = reconf.get_group_descriptions() rospy.logdebug('DynreconfClientWidget.group_desc=%s', group_desc) super(DynreconfClientWidget, self).__init__(ParamUpdater(reconf), group_desc, node_name) # Save and load buttons self.button_widget = QWidget(self) self.button_header = QHBoxLayout(self.button_widget) self.button_header.setContentsMargins(QMargins(0, 0, 0, 0)) self.load_button = QPushButton() self.save_button = QPushButton() self.load_button.setIcon(QIcon.fromTheme('document-open')) self.save_button.setIcon(QIcon.fromTheme('document-save')) self.load_button.clicked[bool].connect(self._handle_load_clicked) self.save_button.clicked[bool].connect(self._handle_save_clicked) self.button_header.addWidget(self.save_button) self.button_header.addWidget(self.load_button) self.setMinimumWidth(150) self.reconf = reconf self.updater.start() self.reconf.config_callback = self.config_callback self._node_grn = node_name
def __init__(self, map_topic='/map', paths=None, polygons=None): super(NavViewWidget, self).__init__() if paths is None: paths = [ '/move_base/NavFn/plan', '/move_base/TrajectoryPlannerROS/local_plan' ] if polygons is None: polygons = ['/move_base/local_costmap/robot_footprint'] self._layout = QVBoxLayout() self._button_layout = QHBoxLayout() self.setAcceptDrops(True) self.setWindowTitle('Navigation Viewer') self.paths = paths self.polygons = polygons self.map_topic = map_topic self._tf = tf.TransformListener() self._set_pose = QPushButton('Set Pose') self._set_goal = QPushButton('Set Goal') self._button_layout.addWidget(self._set_pose) self._button_layout.addWidget(self._set_goal) self._layout.addLayout(self._button_layout) self._nav_view = None self.setLayout(self._layout)
def __init__(self, parent=None, current_values=None): super(BlacklistDialog, self).__init__(parent) self.setWindowTitle("Blacklist") vbox = QVBoxLayout() self.setLayout(vbox) self._blacklist = Blacklist() if isinstance(current_values, list): for val in current_values: self._blacklist.append(val) vbox.addWidget(self._blacklist) controls_layout = QHBoxLayout() add_button = QPushButton(icon=QIcon.fromTheme('list-add')) rem_button = QPushButton(icon=QIcon.fromTheme('list-remove')) ok_button = QPushButton("Ok") cancel_button = QPushButton("Cancel") add_button.clicked.connect(self._add_item) rem_button.clicked.connect(self._remove_item) ok_button.clicked.connect(self.accept) cancel_button.clicked.connect(self.reject) controls_layout.addWidget(add_button) controls_layout.addWidget(rem_button) controls_layout.addStretch(0) controls_layout.addWidget(ok_button) controls_layout.addWidget(cancel_button) vbox.addLayout(controls_layout)
def __init__(self, map_topic='/map', paths=['/move_base/NavFn/plan', '/move_base/TrajectoryPlannerROS/local_plan'], polygons=['/move_base/local_costmap/robot_footprint']): super(NavViewWidget, self).__init__() self._layout = QVBoxLayout() self._button_layout = QHBoxLayout() self.setAcceptDrops(True) self.setWindowTitle('Navigation Viewer') self.paths = paths self.polygons = polygons self.map = map_topic self._tf = tf.TransformListener() self._nav_view = NavView(map_topic, paths, polygons, tf = self._tf, parent = self) self._set_pose = QPushButton('Set Pose') self._set_pose.clicked.connect(self._nav_view.pose_mode) self._set_goal = QPushButton('Set Goal') self._set_goal.clicked.connect(self._nav_view.goal_mode) self._button_layout.addWidget(self._set_pose) self._button_layout.addWidget(self._set_goal) self._layout.addLayout(self._button_layout) self._layout.addWidget(self._nav_view) self.setLayout(self._layout)
def __init__(self, reconf, node_name): """ :type reconf: dynamic_reconfigure.client :type node_name: str """ group_desc = reconf.get_group_descriptions() logging.debug('ParamClientWidget.group_desc=%s', group_desc) super(ParamClientWidget, self).__init__(ParamUpdater(reconf), group_desc, node_name) # Save and load buttons self.button_widget = QWidget(self) self.button_header = QHBoxLayout(self.button_widget) self.button_header.setContentsMargins(QMargins(0, 0, 0, 0)) self.load_button = QPushButton() self.save_button = QPushButton() self.load_button.setIcon(QIcon.fromTheme('document-open')) self.save_button.setIcon(QIcon.fromTheme('document-save')) self.load_button.clicked[bool].connect(self._handle_load_clicked) self.save_button.clicked[bool].connect(self._handle_save_clicked) self.button_header.addWidget(self.save_button) self.button_header.addWidget(self.load_button) self.setMinimumWidth(150) self.reconf = reconf self.updater.start() self.reconf.config_callback = self.config_callback self._node_grn = node_name
def paintEvent(self, ev): QPushButton.paintEvent(self, ev) self.drawRect() self.drawCircle(self.state, QColor(0, 0, 0), False) self.drawCircle(self.center, QColor(0, 0, 0)) self.drawCircle(self.current_pos, QColor(255, 0, 0)) self.drawCrosshair(self.state)
def __init__(self, context): super(SpectrogramPlugin, self).__init__(context) self.setObjectName('Spectrogram') sns.set(style="whitegrid", palette="bright", color_codes=True) self._widget = QWidget() layout = QVBoxLayout() self._widget.setLayout(layout) layout_ = QHBoxLayout() self.lbl_topic = QLabel('Topic:') layout_.addWidget(self.lbl_topic) self.le_topic = QLineEdit() layout_.addWidget(self.le_topic) self.apply_topic = QPushButton("Apply") self.apply_topic.clicked.connect(self.apply_clicked_topic) layout_.addWidget(self.apply_topic) layout.addLayout(layout_) layout_ = QHBoxLayout() self.lbl_lcf = QLabel('Low-cut Freq.[Hz]:') layout_.addWidget(self.lbl_lcf) self.spb_lcf = QSpinBox() self.spb_lcf.setRange(0, 50) self.spb_lcf.setValue(0) layout_.addWidget(self.spb_lcf) self.apply_lcf = QPushButton("Apply") self.apply_lcf.clicked.connect(self.apply_clicked_lcf) layout_.addWidget(self.apply_lcf) layout.addLayout(layout_) layout_ = QHBoxLayout() self.lbl_hcf = QLabel('High-cut Freq.[Hz]:') layout_.addWidget(self.lbl_hcf) self.spb_hcf = QSpinBox() self.spb_hcf.setRange(50, self.vib_freq / 2) self.spb_hcf.setValue(self.vib_freq / 2) layout_.addWidget(self.spb_hcf) self.apply_hcf = QPushButton("Apply") self.apply_hcf.clicked.connect(self.apply_clicked_hcf) layout_.addWidget(self.apply_hcf) layout.addLayout(layout_) #self.fig, self.axes = plt.subplots(2, 1, sharex=True) self.fig = plt.figure() self.ax = self.fig.add_subplot(1, 1, 1) self.canvas = FigureCanvas(self.fig) self.fig.tight_layout() layout.addWidget(self.canvas) context.add_widget(self._widget) self.update_signal.connect(self.update_spectrogram) self.subscriber_signal.connect(self.update_subscriber) self.subscriber_signal.emit('spectrum')
def __init__(self, updater, config, nodename): self.updater = ApplyGroup.ApplyUpdater(updater, self.update_group) super(ApplyGroup, self).__init__(self.updater, config, nodename) self.button = QPushButton('Apply %s' % self.param_name) self.button.clicked.connect(self.updater.apply_update) self.button.setEnabled(False) self.updater.pending_updates.connect(self._pending_cb) self.grid.addRow(self.button)
def __init__(self): super(Dashboard, self).__init__() not_latched = False # latched = True self.publishers = py_trees_ros.utilities.Publishers([ ('scan', "~scan", std_msgs.Empty, not_latched, 1), ('cancel', "~cancel", std_msgs.Empty, not_latched, 1), ]) self.scan_push_button = QPushButton("Scan") self.scan_push_button.setStyleSheet("QPushButton { font-size: 30pt; }") self.scan_push_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.scan_push_button.pressed.connect( functools.partial(self.publish_button_message, self.publishers.scan)) self.cancel_push_button = QPushButton("Cancel") self.cancel_push_button.setStyleSheet( "QPushButton { font-size: 30pt; }") self.cancel_push_button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.cancel_push_button.pressed.connect( functools.partial(self.publish_button_message, self.publishers.cancel)) self.led_strip_flashing = False self.led_strip_on_count = 1 self.led_strip_colour = "grey" self.led_strip_lock = threading.Lock() self.led_strip_timer = QTimer() self.led_strip_timer.timeout.connect(self.led_strip_timer_callback) self.led_strip_label = QLabel("LED Strip") self.led_strip_label.setAlignment(Qt.AlignCenter) self.led_strip_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.led_strip_label.setStyleSheet( "background-color: %s; font-size: 30pt;" % self.led_strip_colour) self.hbox_layout = QGridLayout(self) self.hbox_layout.addWidget(self.scan_push_button) self.hbox_layout.addWidget(self.cancel_push_button) self.hbox_layout.addWidget(self.led_strip_label) self.subscribers = py_trees_ros.utilities.Subscribers([ ("report", "/tree/report", std_msgs.String, self.reality_report_callback), ("led_strip", "/led_strip/display", std_msgs.String, self.led_strip_display_callback) ]) self.led_strip_timer.start(500) # ms
def __init__(self, parent=None): super(ComboBoxDialog, self).__init__() self.number = 0 vbox = QVBoxLayout(self) self.combo_box = QComboBox(self) self.combo_box.activated.connect(self.onActivated) vbox.addWidget(self.combo_box) button = QPushButton() button.setText("Done") button.clicked.connect(self.buttonCallback) vbox.addWidget(button) self.setLayout(vbox)
def setup_group_frame(self, group): layout = QVBoxLayout() # grid for buttons for named targets grid = QGridLayout() grid.setSpacing(1) self.button_group = QButtonGroup(self) row = 0 column = 0 named_targets = self.get_named_targets(group) for target in named_targets: button = QPushButton(target) self.button_group.addButton(button) grid.addWidget(button, row, column) column += 1 if column >= self.MAX_COLUMNS: row += 1 column = 0 self.button_group.buttonClicked.connect(self._handle_button_clicked) # grid for show joint value and move arm buttons/text field joint_values_grid = QGridLayout() joint_values_grid.setSpacing(1) button_show_joint_values = QPushButton('Current Joint Values') button_show_joint_values.clicked[bool].connect( self._handle_show_joint_values_clicked) line_edit = QLineEdit() self.text_joint_values.append(line_edit) button_move_to = QPushButton('Move to') button_move_to.clicked[bool].connect(self._handle_move_to_clicked) joint_values_grid.addWidget(button_show_joint_values, 0, 1) joint_values_grid.addWidget(line_edit, 0, 2) joint_values_grid.addWidget(button_move_to, 0, 3) layout.addLayout(grid) line = QFrame() line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Sunken) layout.addWidget(line) layout.addLayout(joint_values_grid) frame = QFrame() frame.setLayout(layout) return frame
def __init__(self, title="block_pick_and_place"): super(block_pick_and_place, self).__init__() # Initial self.br = tf.TransformBroadcaster() self.tf_listener = tf.TransformListener() self.ik = [0, 0, 0, 0] # Thread lock moveit_commander.roscpp_initialize(sys.argv) self.robot = moveit_commander.RobotCommander() self.scene = moveit_commander.PlanningSceneInterface() self.group = moveit_commander.MoveGroupCommander("arm") display_trajectory_publisher = rospy.Publisher( '/move_group/display_planned_path', moveit_msgs.msg.DisplayTrajectory, queue_size=1) self.gripper_cmd = rospy.Publisher('/gripper_joint/command', Float64, queue_size=1) # safe shutdown rospy.on_shutdown(self.onShutdown) # timer rospy.loginfo("[%s] Initialized " % (rospy.get_name())) self.group.allow_replanning(True) self.group.set_pose_reference_frame("base_link") self.group.set_goal_position_tolerance(0.005) self.group.set_goal_orientation_tolerance(0.05) self.home_pose() self.init_interactive_marker() self.arm_plan_state = False self.vlayout = QVBoxLayout(self) self.gridlayout = QGridLayout() self.vlayout.addLayout(self.gridlayout) # Buttons for randomizing and centering sliders and # Spinbox for on-the-fly selecting number of rows self.CWbutton = QPushButton('Start_to_plan', self) self.CWbutton.clicked.connect(self.start_event) self.vlayout.addWidget(self.CWbutton) self.SPbutton = QPushButton('Stop', self) self.SPbutton.clicked.connect(self.stop_event) self.vlayout.addWidget(self.SPbutton)
def update(self): self.clean() if not self.request: rospy.logwarn('question dialog: no request, update ignored') return req = self.request self._text_browser.setText(req.message) if req.type == QuestionDialogRequest.DISPLAY: # All done, nothing more too see here. self.response = QuestionDialogResponse( QuestionDialogRequest.NO_RESPONSE, "") self.response_ready = True elif req.type == QuestionDialogRequest.CHOICE_QUESTION: for index, options in enumerate(req.options): button = QPushButton(options, self._widget) button.clicked.connect(partial(self.handle_button, index)) row = index / 3 col = index % 3 self._button_layout.addWidget(button, row, col) self.buttons.append(button) elif req.type == QuestionDialogRequest.TEXT_QUESTION: self.text_label = QLabel("Enter here: ", self._widget) self._button_layout.addWidget(self.text_label, 0, 0) self.text_input = QLineEdit(self._widget) self.text_input.editingFinished.connect(self.handle_text) self._button_layout.addWidget(self.text_input, 0, 1)
def update_buttons(self): """ Update buttons in Qt window. """ rospy.loginfo('level selector: update_buttons called') self.clean() for index, level in enumerate(self.levels): 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 __init__(self, context, actions): super(ActionClientContainerWidget, self).__init__() grid = QGridLayout() grid.setSpacing(1) MAX_COLUMNS = 2 self.setObjectName('ActionClientContainerWidget') self.clear_button = QPushButton("Clear all") self.clear_button.clicked[bool].connect(self._handle_clear_clicked) grid.addWidget(self.clear_button, 0, 0) self.widgets = [] row = 1 column = 0 for k in sorted(actions.keys()): action_name = k widget = ActionClientWidget(context, action_name, actions[k]) grid.addWidget(widget, row, column) self.widgets.append(widget) column += 1 if column >= MAX_COLUMNS: row += 1 column = 0 self.setLayout(grid)
def __init__(self, context): ''' Initialie the PID tuner Parameters: N/A Returns: N/A ''' #Initialize with qt_gui plugin for ros super(PID_Tuner, self).__init__(context) self.layout = QVBoxLayout() self._widget = QWidget() self._widget.setLayout(self.layout) #Import a generic pid tunning widget for each pid controller self.velocity_pid_tuner_widget = PID_Tuner_Generic_Widget() self.steering_pid_tuner_widget = PID_Tuner_Generic_Widget() self.pid_tuner_widgets = [ self.velocity_pid_tuner_widget, self.steering_pid_tuner_widget ] #Add button for sending the gains self.update_gains_btn = QPushButton("Update Gains") self.update_gains_btn.clicked.connect(self._update_gains) #Add the pid tuners to a layout for pid_tuner_widget in self.pid_tuner_widgets: self.layout.addWidget(pid_tuner_widget) self.layout.addWidget(self.update_gains_btn) context.add_widget(self._widget)
def __init__(self): super(NodeWidgetsContainer, self).__init__() yaml_file = rospy.get_param("~config_file") stream = open(yaml_file, "r") nodes = yaml.load(stream) rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('mcr_event_gui'), 'ros', 'resources', 'NodeWidgetsContainer.ui') loadUi(ui_file, self) grid = QGridLayout() grid.setSpacing(1) MAX_COLUMNS = 2 self.setObjectName('NodeWidgetsContainer') self.clear_button = QPushButton("Clear all") self.clear_button.clicked[bool].connect(self._handle_clear_clicked) self.stop_button = QPushButton("Stop all") self.stop_button.clicked[bool].connect(self._handle_stop_clicked) grid.addWidget(self.clear_button, 0, 0) grid.addWidget(self.stop_button, 0, 1) self.widgets = [] row = 1 column = 0 for k in sorted(nodes.keys()): node_name = k widget = NodeEventsWidget(node_name, nodes[k]) width = widget.width() height = widget.height() grid.addWidget(widget, row, column) grid.setColumnMinimumWidth(column, width) grid.setRowMinimumHeight(row, height) self.widgets.append(widget) column += 1 if column >= MAX_COLUMNS: row += 1 column = 0 self.setLayout(grid)
def __init__(self, updater, config): self.updater = ApplyGroup.ApplyUpdater(updater) super(ApplyGroup, self).__init__(self.updater, config) self.button = QPushButton("Apply %s" % self.name) self.button.clicked.connect(self.updater.apply_update) rows = self.grid.rowCount() self.grid.addWidget(self.button, rows + 1, 1, Qt.AlignRight)
def __init__(self, updater, config, nodename): """ :param config: :type config: Dictionary? defined in dynamic_reconfigure.client.Client :type nodename: str """ super(GroupWidget, self).__init__() self.state = config['state'] self.param_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) logging.debug('Groups node name={}'.format(nodename)) self.nodename_qlabel.setText(nodename)
def __init__(self, parent=None): super(LineEditDialog, self).__init__() self.value = None vbox = QVBoxLayout(self) # combo box model = QtGui.QStandardItemModel(self) for elm in rospy.get_param_names(): model.setItem(model.rowCount(), 0, QtGui.QStandardItem(elm)) self.combo_box = QComboBox(self) self.line_edit = QLineEdit() self.combo_box.setLineEdit(self.line_edit) self.combo_box.setCompleter(QCompleter()) self.combo_box.setModel(model) self.combo_box.completer().setModel(model) self.combo_box.lineEdit().setText('') vbox.addWidget(self.combo_box) # button button = QPushButton() button.setText("Done") button.clicked.connect(self.buttonCallback) vbox.addWidget(button) self.setLayout(vbox)
def add_buttons(self, colors): vbx = QVBoxLayout() i = 1 for color in colors: but = QPushButton('Color {} ({})'.format(color, i)) but.clicked.connect(self.clicked(color)) but_short = QShortcut(QKeySequence("Ctrl+" + str(i)), self) but_short.activated.connect(self.clicked(color)) i += 1 vbx.addWidget(but) vbx.addStretch(1) self.color_buttons.setLayout(vbx)
class NodeSelection(QWidget): def __init__(self, parent): super(NodeSelection, self).__init__() self.parent_widget = parent self.selected_nodes = [] self.setWindowTitle("Select the nodes you want to record") self.resize(500, 700) self.area = QScrollArea(self) self.main_widget = QWidget(self.area) self.ok_button = QPushButton("Done", self) self.ok_button.clicked.connect(self.onButtonClicked) self.ok_button.setEnabled(False) self.main_vlayout = QVBoxLayout(self) self.main_vlayout.addWidget(self.area) self.main_vlayout.addWidget(self.ok_button) self.setLayout(self.main_vlayout) self.selection_vlayout = QVBoxLayout(self) self.node_list = rosnode.get_node_names() self.node_list.sort() for node in self.node_list: self.addCheckBox(node) self.main_widget.setLayout(self.selection_vlayout) self.show() def addCheckBox(self, node): item = QCheckBox(node, self) item.stateChanged.connect(lambda x: self.updateNode(x, node)) self.selection_vlayout.addWidget(item) def updateNode(self, state, node): if state == Qt.Checked: self.selected_nodes.append(node) else: self.selected_nodes.remove(node) if len(self.selected_nodes) > 0: self.ok_button.setEnabled(True) else: self.ok_button.setEnabled(False) def onButtonClicked(self): master = rosgraph.Master('rqt_bag_recorder') state = master.getSystemState() subs = [ t for t, l in state[1] if len([ node_name for node_name in self.selected_nodes if node_name in l ]) > 0 ] # print subs # print len(subs) for topic in subs: self.parent_widget.changeTopicCheckState(topic, Qt.Checked) self.parent_widget.updateList(Qt.Checked, topic, topic) self.close()
def __init__(self, parent, name, timeline): """ :param name: Name of inspecting diagnostic status :param timeline: Timeline object from which a status is fetched """ #TODO(Isaac) UI construction that currently is done in this method, # needs to be done in .ui file. super(InspectorWindow, self).__init__(parent=parent) self.setWindowTitle(name) self._name = name self.layout_vertical = QVBoxLayout(self) self.disp = StatusSnapshot(parent=self) self.layout_vertical.addWidget(self.disp, 1) self._message_updated_processing = False self._queue_updated_processing = False self.timeline = timeline self.timeline.message_updated.connect( self.message_updated, Qt.DirectConnection) self.timeline.queue_updated.connect( self.queue_updated, Qt.DirectConnection) self._message_updated.connect( self._signal_message_updated, Qt.QueuedConnection) self._queue_updated.connect( self._signal_queue_updated, Qt.QueuedConnection) self.timeline_pane = TimelinePane(self, self.timeline.paused) self.timeline_pane.pause_changed.connect(self.timeline.set_paused) self.timeline_pane.position_changed.connect(self.timeline.set_position) self.timeline.pause_changed.connect(self.timeline_pane.set_paused) self.timeline.position_changed.connect(self.timeline_pane.set_position) self.layout_vertical.addWidget(self.timeline_pane, 0) self.snapshot = QPushButton("Snapshot") self.snapshot.clicked.connect(self._take_snapshot) self.layout_vertical.addWidget(self.snapshot) self.snaps = [] self.setLayout(self.layout_vertical) # TODO better to be configurable where to appear. self.resize(400, 600)
def __init__(self, btnText): super(BagSelector, self).__init__() # init the elements self.bagEdit = QLineEdit() self.bagBtn = QPushButton(btnText) # connect the signals to the slots self.bagEdit.textChanged.connect(self.pathChanged) self.bagBtn.clicked.connect(self.btnClicked) self.fileName = "" # layout layout = QHBoxLayout() layout.addWidget(self.bagEdit) layout.addWidget(self.bagBtn) self.setLayout(layout)
def __init__(self, status, close_callback): """ :type status: DiagnosticStatus :param close_callback: When the instance of this class (InspectorWindow) terminates, this callback gets called. """ #TODO(Isaac) UI construction that currently is done in this method, # needs to be done in .ui file. super(InspectorWindow, self).__init__() self.status = status self._close_callback = close_callback self.setWindowTitle(status.name) self.paused = False self.layout_vertical = QVBoxLayout(self) self.disp = QTextEdit(self) self.snapshot = QPushButton("StatusSnapshot") self.timeline_pane = TimelinePane(self) self.timeline_pane.set_timeline_data(Util.SECONDS_TIMELINE, self.get_color_for_value, self.on_pause) self.layout_vertical.addWidget(self.disp, 1) self.layout_vertical.addWidget(self.timeline_pane, 0) self.layout_vertical.addWidget(self.snapshot) self.snaps = [] self.snapshot.clicked.connect(self._take_snapshot) self._sig_write.connect(self._write_key_val) self._sig_newline.connect(lambda: self.disp.insertPlainText('\n')) self._sig_clear.connect(lambda: self.disp.clear()) self._sig_close_window.connect(self._close_callback) self.setLayout(self.layout_vertical) # TODO better to be configurable where to appear. self.setGeometry(0, 0, 400, 600) self.show() self.update_status_display(status)
class NodeSelection(QWidget): def __init__(self, parent): super(NodeSelection, self).__init__() self.parent_widget = parent self.selected_nodes = [] self.setWindowTitle("Select the nodes you want to record") self.resize(500, 700) self.area = QScrollArea(self) self.main_widget = QWidget(self.area) self.ok_button = QPushButton("Done", self) self.ok_button.clicked.connect(self.onButtonClicked) self.ok_button.setEnabled(False) self.main_vlayout = QVBoxLayout(self) self.main_vlayout.addWidget(self.area) self.main_vlayout.addWidget(self.ok_button) self.setLayout(self.main_vlayout) self.selection_vlayout = QVBoxLayout(self) self.node_list = rosnode.get_node_names() self.node_list.sort() for node in self.node_list: self.addCheckBox(node) self.main_widget.setLayout(self.selection_vlayout) self.show() def addCheckBox(self, node): item = QCheckBox(node, self) item.stateChanged.connect(lambda x: self.updateNode(x, node)) self.selection_vlayout.addWidget(item) def updateNode(self, state, node): if state == Qt.Checked: self.selected_nodes.append(node) else: self.selected_nodes.remove(node) if len(self.selected_nodes) > 0: self.ok_button.setEnabled(True) else: self.ok_button.setEnabled(False) def onButtonClicked(self): master = rosgraph.Master('rqt_bag_recorder') state = master.getSystemState() subs = [t for t, l in state[1] if len([node_name for node_name in self.selected_nodes if node_name in l]) > 0] for topic in subs: self.parent_widget.changeTopicCheckState(topic, Qt.Checked) self.parent_widget.updateList(Qt.Checked, topic) self.close()
def __init__(self, linesList, parent=None): super(DelPlotDialog, self).__init__() self.linesList = linesList # list of the axes self.parent = parent # init the components: self.setWindowTitle("Delete Graph") self.resize(300, 200) self.linesListWidget = QListWidget(self) self.refreshList(self.linesList) self.__btn = QPushButton("Delete") # connect signals self.__btn.clicked.connect(self.btnPressed) # layout: layout = QVBoxLayout() layout.addWidget(self.linesListWidget) layout.addWidget(self.__btn) self.setLayout(layout)
def __init__(self, params, id_radio): super(inputDialog, self).__init__() self.id_radio = id_radio self.center() layout = QFormLayout() self.label_items = [] self.label_comment = dict() self.client_answers_items = [] self.greather_conditions = [] self.button_clicked = False # print params for item in params: param = item[0] label = item[1] cond = item[2] if not label == "": label = " (%s)" % label self.greather_conditions.append((param, cond)) label_item = QLabel(param + label, self) # self.label_items[param] = QLabel(param + label, self) label_item.setAlignment(Qt.AlignCenter) self.label_items.append(param) client_answers = QLineEdit() self.client_answers_items.append(client_answers) # self.label_comment[label] = QLabel(label, self) # self.label_comment[label].setAlignment(Qt.AlignCenter) # layout.addWidget(self.label_comment[label]) layout.addRow(label_item, client_answers) self.ok_button = QPushButton("ok", self) self.ok_button.clicked.connect(self.onButtonClicked) layout.addWidget(self.ok_button) self.setLayout(layout) self.setWindowTitle("Update Parameters") self.show()
def __init__(self, parent): super(NodeSelection, self).__init__() self.parent_widget = parent self.selected_nodes = [] self.setWindowTitle("Select the nodes you want to record") self.resize(500, 700) self.area = QScrollArea(self) self.main_widget = QWidget(self.area) self.ok_button = QPushButton("Done", self) self.ok_button.clicked.connect(self.onButtonClicked) self.ok_button.setEnabled(False) self.main_vlayout = QVBoxLayout(self) self.main_vlayout.addWidget(self.area) self.main_vlayout.addWidget(self.ok_button) self.setLayout(self.main_vlayout) self.selection_vlayout = QVBoxLayout(self) self.node_list = rosnode.get_node_names() self.node_list.sort() for node in self.node_list: self.addCheckBox(node) self.main_widget.setLayout(self.selection_vlayout) self.show()
def __init__(self, updater, config, nodename): ''' :param config: :type config: Dictionary? defined in dynamic_reconfigure.client.Client :type nodename: str ''' super(GroupWidget, self).__init__() self.state = config['state'] self.param_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)
class TopicSelection(QWidget): recordSettingsSelected = Signal(bool, list) def __init__(self): super(TopicSelection, self).__init__() master = rosgraph.Master('rqt_bag_recorder') self.setWindowTitle("Select the topics you want to record") self.resize(500, 700) self.topic_list = [] self.selected_topics = [] self.items_list = [] self.area = QScrollArea(self) self.main_widget = QWidget(self.area) self.ok_button = QPushButton("Record", self) self.ok_button.clicked.connect(self.onButtonClicked) self.ok_button.setEnabled(False) self.main_vlayout = QVBoxLayout(self) self.main_vlayout.addWidget(self.area) self.main_vlayout.addWidget(self.ok_button) self.setLayout(self.main_vlayout) self.selection_vlayout = QVBoxLayout(self) self.item_all = QCheckBox("All", self) self.item_all.stateChanged.connect(self.updateList) self.selection_vlayout.addWidget(self.item_all) topic_data_list = master.getPublishedTopics('') topic_data_list.sort() for topic, datatype in topic_data_list: self.addCheckBox(topic) self.main_widget.setLayout(self.selection_vlayout) self.area.setWidget(self.main_widget) self.show() def addCheckBox(self, topic): self.topic_list.append(topic) item = QCheckBox(topic, self) item.stateChanged.connect(lambda x: self.updateList(x,topic)) self.items_list.append(item) self.selection_vlayout.addWidget(item) def updateList(self, state, topic = None): if topic is None: # The "All" checkbox was checked / unchecked if state == Qt.Checked: self.item_all.setTristate(False) for item in self.items_list: if item.checkState() == Qt.Unchecked: item.setCheckState(Qt.Checked) elif state == Qt.Unchecked: self.item_all.setTristate(False) for item in self.items_list: if item.checkState() == Qt.Checked: item.setCheckState(Qt.Unchecked) else: if state == Qt.Checked: self.selected_topics.append(topic) else: self.selected_topics.remove(topic) if self.item_all.checkState()==Qt.Checked: self.item_all.setCheckState(Qt.PartiallyChecked) if self.selected_topics == []: self.ok_button.setEnabled(False) else: self.ok_button.setEnabled(True) def onButtonClicked(self): self.close() self.recordSettingsSelected.emit((self.item_all.checkState() == Qt.Checked), self.selected_topics)
class PlotWidget(QWidget): def __init__(self, timeline, parent, topic): super(PlotWidget, self).__init__(parent) self.setObjectName('PlotWidget') self.timeline = timeline msg_type = self.timeline.get_datatype(topic) self.msgtopic = topic self.start_stamp = self.timeline._get_start_stamp() self.end_stamp = self.timeline._get_end_stamp() # the current region-of-interest for our bag file # all resampling and plotting is done with these limits self.limits = [0,(self.end_stamp-self.start_stamp).to_sec()] rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_bag_plugins'), 'resource', 'plot.ui') loadUi(ui_file, self) self.message_tree = MessageTree(msg_type, self) self.data_tree_layout.addWidget(self.message_tree) # TODO: make this a dropdown with choices for "Auto", "Full" and # "Custom" # I continue to want a "Full" option here self.auto_res.stateChanged.connect(self.autoChanged) self.resolution.editingFinished.connect(self.settingsChanged) self.resolution.setValidator(QDoubleValidator(0.0,1000.0,6,self.resolution)) self.timeline.selected_region_changed.connect(self.region_changed) self.recompute_timestep() self.plot = DataPlot(self) self.plot.set_autoscale(x=False) self.plot.set_autoscale(y=DataPlot.SCALE_VISIBLE) self.plot.autoscroll(False) self.plot.set_xlim(self.limits) self.data_plot_layout.addWidget(self.plot) self._home_button = QPushButton() self._home_button.setToolTip("Reset View") self._home_button.setIcon(QIcon.fromTheme('go-home')) self._home_button.clicked.connect(self.home) self.plot_toolbar_layout.addWidget(self._home_button) self._config_button = QPushButton("Configure Plot") self._config_button.clicked.connect(self.plot.doSettingsDialog) self.plot_toolbar_layout.addWidget(self._config_button) self.set_cursor(0) self.paths_on = set() self._lines = None # get bag from timeline bag = None start_time = self.start_stamp while bag is None: bag,entry = self.timeline.get_entry(start_time, topic) if bag is None: start_time = self.timeline.get_entry_after(start_time)[1].time self.bag = bag # get first message from bag msg = bag._read_message(entry.position) self.message_tree.set_message(msg[1]) # state used by threaded resampling self.resampling_active = False self.resample_thread = None self.resample_fields = set() def set_cursor(self, position): self.plot.vline(position, color=DataPlot.RED) self.plot.redraw() def add_plot(self, path): self.resample_data([path]) def update_plot(self): if len(self.paths_on)>0: self.resample_data(self.paths_on) def remove_plot(self, path): self.plot.remove_curve(path) self.paths_on.remove(path) self.plot.redraw() def load_data(self): """get a generator for the specified time range on our bag""" return self.bag.read_messages(self.msgtopic, self.start_stamp+rospy.Duration.from_sec(self.limits[0]), self.start_stamp+rospy.Duration.from_sec(self.limits[1])) def resample_data(self, fields): if self.resample_thread: # cancel existing thread and join self.resampling_active = False self.resample_thread.join() for f in fields: self.resample_fields.add(f) # start resampling thread self.resampling_active = True self.resample_thread = threading.Thread(target=self._resample_thread) # explicitly mark our resampling thread as a daemon, because we don't # want to block program exit on a long resampling operation self.resample_thread.setDaemon(True) self.resample_thread.start() def _resample_thread(self): # TODO: # * look into doing partial display updates for long resampling # operations # * add a progress bar for resampling operations x = {} y = {} for path in self.resample_fields: x[path] = [] y[path] = [] msgdata = self.load_data() for entry in msgdata: # detect if we're cancelled and return early if not self.resampling_active: return for path in self.resample_fields: # this resampling method is very unstable, because it picks # representative points rather than explicitly representing # the minimum and maximum values present within a sample # If the data has spikes, this is particularly bad because they # will be missed entirely at some resolutions and offsets if x[path]==[] or (entry[2]-self.start_stamp).to_sec()-x[path][-1] >= self.timestep: y_value = entry[1] for field in path.split('.'): index = None if field.endswith(']'): field = field[:-1] field, _, index = field.rpartition('[') y_value = getattr(y_value, field) if index: index = int(index) y_value = y_value[index] y[path].append(y_value) x[path].append((entry[2]-self.start_stamp).to_sec()) # TODO: incremental plot updates would go here... # we should probably do incremental updates based on time; # that is, push new data to the plot maybe every .5 or .1 # seconds # time is a more useful metric than, say, messages loaded or # percentage, because it will give a reasonable refresh rate # without overloading the computer # if we had a progress bar, we could emit a signal to update it here # update the plot with final resampled data for path in self.resample_fields: if len(x[path]) < 1: qWarning("Resampling resulted in 0 data points for %s" % path) else: if path in self.paths_on: self.plot.clear_values(path) self.plot.update_values(path, x[path], y[path]) else: self.plot.add_curve(path, path, x[path], y[path]) self.paths_on.add(path) self.plot.redraw() self.resample_fields.clear() self.resampling_active = False def recompute_timestep(self): # this is only called if we think the timestep has changed; either # by changing the limits or by editing the resolution limits = self.limits if self.auto_res.isChecked(): timestep = round((limits[1]-limits[0])/200.0,5) else: timestep = float(self.resolution.text()) self.resolution.setText(str(timestep)) self.timestep = timestep def region_changed(self, start, end): # this is the only place where self.limits is set limits = [ (start - self.start_stamp).to_sec(), (end - self.start_stamp).to_sec() ] # cap the limits to the start and end of our bag file if limits[0]<0: limits = [0.0,limits[1]] if limits[1]>(self.end_stamp-self.start_stamp).to_sec(): limits = [limits[0],(self.end_stamp-self.start_stamp).to_sec()] self.limits = limits self.recompute_timestep() self.plot.set_xlim(limits) self.plot.redraw() self.update_plot() def settingsChanged(self): # resolution changed. recompute the timestep and resample self.recompute_timestep() self.update_plot() def autoChanged(self, state): if state==2: # auto mode enabled. recompute the timestep and resample self.resolution.setDisabled(True) self.recompute_timestep() self.update_plot() else: # auto mode disabled. enable the resolution text box # no change to resolution yet, so no need to redraw self.resolution.setDisabled(False) def home(self): # TODO: re-add the button for this. It's useful for restoring the # X and Y limits so that we can see all of the data # effectively a "zoom all" button # reset the plot to our current limits self.plot.set_xlim(self.limits) # redraw the plot; this forces a Y autoscaling self.plot.redraw()
def __init__(self, timeline, parent, topic): super(PlotWidget, self).__init__(parent) self.setObjectName('PlotWidget') self.timeline = timeline msg_type = self.timeline.get_datatype(topic) self.msgtopic = topic self.start_stamp = self.timeline._get_start_stamp() self.end_stamp = self.timeline._get_end_stamp() # the current region-of-interest for our bag file # all resampling and plotting is done with these limits self.limits = [0,(self.end_stamp-self.start_stamp).to_sec()] rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_bag_plugins'), 'resource', 'plot.ui') loadUi(ui_file, self) self.message_tree = MessageTree(msg_type, self) self.data_tree_layout.addWidget(self.message_tree) # TODO: make this a dropdown with choices for "Auto", "Full" and # "Custom" # I continue to want a "Full" option here self.auto_res.stateChanged.connect(self.autoChanged) self.resolution.editingFinished.connect(self.settingsChanged) self.resolution.setValidator(QDoubleValidator(0.0,1000.0,6,self.resolution)) self.timeline.selected_region_changed.connect(self.region_changed) self.recompute_timestep() self.plot = DataPlot(self) self.plot.set_autoscale(x=False) self.plot.set_autoscale(y=DataPlot.SCALE_VISIBLE) self.plot.autoscroll(False) self.plot.set_xlim(self.limits) self.data_plot_layout.addWidget(self.plot) self._home_button = QPushButton() self._home_button.setToolTip("Reset View") self._home_button.setIcon(QIcon.fromTheme('go-home')) self._home_button.clicked.connect(self.home) self.plot_toolbar_layout.addWidget(self._home_button) self._config_button = QPushButton("Configure Plot") self._config_button.clicked.connect(self.plot.doSettingsDialog) self.plot_toolbar_layout.addWidget(self._config_button) self.set_cursor(0) self.paths_on = set() self._lines = None # get bag from timeline bag = None start_time = self.start_stamp while bag is None: bag,entry = self.timeline.get_entry(start_time, topic) if bag is None: start_time = self.timeline.get_entry_after(start_time)[1].time self.bag = bag # get first message from bag msg = bag._read_message(entry.position) self.message_tree.set_message(msg[1]) # state used by threaded resampling self.resampling_active = False self.resample_thread = None self.resample_fields = set()
class DynreconfClientWidget(GroupWidget): """ A wrapper of dynamic_reconfigure.client instance. Represents a widget where users can view and modify ROS params. """ def __init__(self, reconf, node_name): """ :type reconf: dynamic_reconfigure.client :type node_name: str """ group_desc = reconf.get_group_descriptions() rospy.logdebug('DynreconfClientWidget.group_desc=%s', group_desc) super(DynreconfClientWidget, self).__init__(ParamUpdater(reconf), group_desc, node_name) # Save and load buttons self.button_widget = QWidget(self) self.button_header = QHBoxLayout(self.button_widget) self.button_header.setContentsMargins(QMargins(0, 0, 0, 0)) self.load_button = QPushButton() self.save_button = QPushButton() self.load_button.setIcon(QIcon.fromTheme('document-open')) self.save_button.setIcon(QIcon.fromTheme('document-save')) self.load_button.clicked[bool].connect(self._handle_load_clicked) self.save_button.clicked[bool].connect(self._handle_save_clicked) self.button_header.addWidget(self.save_button) self.button_header.addWidget(self.load_button) self.setMinimumWidth(150) self.reconf = reconf self.updater.start() self.reconf.config_callback = self.config_callback self._node_grn = node_name def get_node_grn(self): return self._node_grn def config_callback(self, config): #TODO: Think about replacing callback architecture with signals. if config: # TODO: should use config.keys but this method doesnt exist names = [name for name, v in config.items()] # v isn't used but necessary to get key and put it into dict. rospy.logdebug('config_callback name={} v={}'.format(name, v)) for widget in self.editor_widgets: if isinstance(widget, EditorWidget): if widget.param_name in names: rospy.logdebug('EDITOR widget.param_name=%s', widget.param_name) widget.update_value(config[widget.param_name]) elif isinstance(widget, GroupWidget): cfg = find_cfg(config, widget.param_name) rospy.logdebug('GROUP widget.param_name=%s', widget.param_name) widget.update_group(cfg) def _handle_load_clicked(self): filename = QFileDialog.getOpenFileName( self, self.tr('Load from File'), '.', self.tr('YAML file {.yaml} (*.yaml)')) if filename[0] != '': self.load_param(filename[0]) def _handle_save_clicked(self): filename = QFileDialog.getSaveFileName( self, self.tr('Save parameters to file...'), '.', self.tr('YAML files {.yaml} (*.yaml)')) if filename[0] != '': self.save_param(filename[0]) def save_param(self, filename): configuration = self.reconf.get_configuration() if configuration is not None: with file(filename, 'w') as f: yaml.dump(configuration, f) def load_param(self, filename): with file(filename, 'r') as f: configuration = {} for doc in yaml.load_all(f.read()): configuration.update(doc) self.reconf.update_configuration(configuration) def close(self): self.reconf.close() self.updater.stop() for w in self.editor_widgets: w.close() self.deleteLater() def filter_param(self, filter_key): #TODO impl pass