def __init__(self): QWidget.__init__(self) rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_bag_annotation'), 'resource', 'export_widget.ui') loadUi(ui_file, self) self.add_topic_button.setIcon(QIcon.fromTheme('list-add')) self.remove_topic_button.setIcon(QIcon.fromTheme('list-remove')) self.refresh_button.setIcon(QIcon.fromTheme('view-refresh')) self.add_topic_button.clicked[bool].connect(self._handle_add_topic_clicked) self.remove_topic_button.clicked[bool].connect(self._handle_remove_topic_clicked) self.refresh_button.clicked[bool].connect(self._handle_refresh_clicked) self.export_button.clicked[bool].connect(self._handle_export_clicked) self.export_location_edit.setPlainText("./export_file.txt") self.rospack = rospkg.RosPack() self._exported_topics = list() self._exported_publisher_info = list() self._annotations = list() self._active_topics = list() self._dt = 0.1 self._current_topic_paths = dict() self._current_msg_paths = dict() self._id_counter = 0 self.current_output = ""
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): super(MainWidget, self).__init__() self.setObjectName('MainWidget') rospack = rospkg.RosPack() ui_file = rospack.get_path('rqt_joint_trajectory_plot')+'/resource/JointTrajectoryPlot.ui' loadUi(ui_file, self) self.refresh_button.setIcon(QIcon.fromTheme('reload')) self.pause_button.setIcon(QIcon.fromTheme('media-playback-pause')) self.handler = None self.joint_names = [] self.timer = QTimer(self) self.timer.timeout.connect(self.update) self.plot_widget = PlotWidget(self) self.plot_layout.addWidget(self.plot_widget) self.draw_curves.connect(self.plot_widget.draw_curves) self.time = None (self.dis, self.vel, self.acc, self.eff) = ({}, {}, {}, {}) # refresh topics list in the combobox self.refresh_topics() self.change_topic() self.refresh_button.clicked.connect(self.refresh_topics) self.topic_combox.currentIndexChanged.connect(self.change_topic) self.select_tree.itemChanged.connect(self.update_checkbox)
def __init__(self, ros_package): super(GraphWidget, self).__init__() self._current_graph = None self._lock = Lock() self._load_ui(ros_package) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) factory = DmgItemFactory() factory.set_color(QColor(50, 50, 50)) factory.set_highlighted_color(QColor(0, 150, 0)) self._dot_to_qt = DotToQtGenerator(factory) self.initialized = False self.setObjectName('GraphWidget') self.graphics_view.setScene(self._scene) self.open_button.setIcon(QIcon.fromTheme('document-open')) self.open_button.pressed.connect(self._import) self.export_button.setIcon(QIcon.fromTheme('document-export')) self.export_button.pressed.connect(self._export) self.fit_to_view_button.setIcon(QIcon.fromTheme('zoom-fit-best')) self.fit_to_view_button.pressed.connect(self._fit_to_view) self.decision_graphs_combo_box.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) self.decision_graphs_combo_box.currentIndexChanged['QString'].connect(self._graph_item_changed) self._dot_processor = DotProcessor(self._dot_to_qt) self.decision_graphs = dict() self.states = dict()
def __init__(self, url=None): """ Class to load a webpage in a widget. :param url: If url is empty then a navigation bar is shown otherwise the url is loaded and the navigation bar is hidden, ''str'' """ super(WebWidget, self).__init__() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_web'), 'resource', 'web_widget.ui') loadUi(ui_file, self) self.setObjectName('WebWidget') self._loading = False self._stop_icon = QIcon.fromTheme('process-stop') self._reload_icon = QIcon.fromTheme('view-refresh') self._working_icon = QIcon.fromTheme('process-working') self._completer_word_list = [''] self._view = QWebView() self.verticalLayout.addWidget(self._view) if url is None: self.set_url("http://ros.org", True) else: self.set_url(url, False) self.url_lineedit.returnPressed.connect(self._handle_url_change) self._view.loadFinished[bool].connect(self._handle_load_finished) self.reload_button.clicked.connect(self._handle_reload_clicked) self._view.linkClicked.connect(self._handle_link_clicked) self._view.urlChanged[QUrl].connect(self._handle_url_changed)
def on_pushButton_calibrate_clicked(self): self._widget.pushButton_calibrate.setEnabled(False) status_icon = QIcon.fromTheme('stock_no') # Fill request information request = self._selected_service['service_class']._request_class() request.target_hue.data = self._widget.spinBox_hue.value() request.mult_diffs.data = self._widget.spinBox_diff.value() request.mult_sat.data = self._widget.spinBox_sat.value() try: # Call service response = self._selected_service['service_proxy'](request) except rospy.ServiceException as e: qWarning('on_pushButton_calibrate_clicked(): error calling service "%s":\n%s' % (self._selected_service['service_name'], e)) else: # Get debug image and show img = response.image_debug qImage = QImage(img.data, img.width, img.height, img.step, QImage.Format_RGB888) qPixmap = QPixmap() qPixmap.convertFromImage(qImage) pixmapItem = QGraphicsPixmapItem(qPixmap) self._qGraphicsScene.clear() self._qGraphicsScene.addItem(pixmapItem) self._widget.graphicsView.fitInView(QRectF(qPixmap.rect()), Qt.KeepAspectRatio) if response.success.data == True: status_icon = QIcon.fromTheme('stock_yes') self._widget.label_status.setPixmap(status_icon.pixmap(status_icon.actualSize(QSize(24, 24)))) self._widget.pushButton_calibrate.setEnabled(True)
def __init__(self): super(ServiceCallerWidget, self).__init__() self.setObjectName('ServiceCallerWidget') # create context for the expression eval statement self._eval_locals = {} for module in (math, random, time): self._eval_locals.update(module.__dict__) self._eval_locals['genpy'] = genpy del self._eval_locals['__name__'] del self._eval_locals['__doc__'] rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_service_caller'), 'resource', 'ServiceCaller.ui') loadUi(ui_file, self, {'ExtendedComboBox': ExtendedComboBox}) self.refresh_services_button.setIcon(QIcon.fromTheme('view-refresh')) self.call_service_button.setIcon(QIcon.fromTheme('call-start')) self._column_index = {} for column_name in self.column_names: self._column_index[column_name] = len(self._column_index) self._service_info = None self.on_refresh_services_button_clicked() self.request_tree_widget.itemChanged.connect(self.request_tree_widget_itemChanged)
def __init__(self, initial_topics=None, start_paused=False): super(PlotWidget, self).__init__() self.setObjectName('PlotWidget') self._initial_topics = initial_topics rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_plot'), 'resource', 'plot.ui') loadUi(ui_file, self) self.subscribe_topic_button.setIcon(QIcon.fromTheme('list-add')) self.remove_topic_button.setIcon(QIcon.fromTheme('list-remove')) self.pause_button.setIcon(QIcon.fromTheme('media-playback-pause')) self.clear_button.setIcon(QIcon.fromTheme('edit-clear')) self.data_plot = None self.subscribe_topic_button.setEnabled(False) if start_paused: self.pause_button.setChecked(True) self._topic_completer = TopicCompleter(self.topic_edit) self._topic_completer.update_topics() self.topic_edit.setCompleter(self._topic_completer) self._start_time = rospy.get_time() self._rosdata = {} self._remove_topic_menu = QMenu() # init and start update timer for plot self._update_plot_timer = QTimer(self) self._update_plot_timer.timeout.connect(self.update_plot)
def __init__(self): super(MessageDataModel, self).__init__() self._messages = MessageList() self._message_limit = 20000 self._info_icon = QIcon.fromTheme('dialog-information') self._warning_icon = QIcon.fromTheme('dialog-warning') self._error_icon = QIcon.fromTheme('dialog-error')
def set_menu(self, menu): self._menu_manager = MenuManager(menu) self._perspective_mapper = QSignalMapper(menu) self._perspective_mapper.mapped[str].connect(self.switch_perspective) # generate menu create_action = QAction('&Create perspective...', self._menu_manager.menu) create_action.setIcon(QIcon.fromTheme('list-add')) create_action.triggered.connect(self._on_create_perspective) self._menu_manager.add_suffix(create_action) self._remove_action = QAction('&Remove perspective...', self._menu_manager.menu) self._remove_action.setEnabled(False) self._remove_action.setIcon(QIcon.fromTheme('list-remove')) self._remove_action.triggered.connect(self._on_remove_perspective) self._menu_manager.add_suffix(self._remove_action) self._menu_manager.add_suffix(None) import_action = QAction('&Import...', self._menu_manager.menu) import_action.setIcon(QIcon.fromTheme('document-open')) import_action.triggered.connect(self._on_import_perspective) self._menu_manager.add_suffix(import_action) export_action = QAction('&Export...', self._menu_manager.menu) export_action.setIcon(QIcon.fromTheme('document-save-as')) export_action.triggered.connect(self._on_export_perspective) self._menu_manager.add_suffix(export_action) # add perspectives to menu for name in self.perspectives: if not name.startswith(self.HIDDEN_PREFIX): self._add_perspective_action(name)
def on_ctrl_list_tree_widget_customContextMenuRequested(self, pos): ctrlman_ns = self.cm_namespace_combo.currentText() item = self.ctrl_list_tree_widget.itemAt(pos) if item is None: return ctrl_name = item.data(0, Qt.UserRole) ctrl_state = self._ctrlers[ctrl_name]['state'] # show context menu menu = QMenu(self) if ctrl_state == 'running': action_stop = menu.addAction( QIcon.fromTheme('media-playback-stop'), 'Stop Controller') action_kill = menu.addAction( QIcon.fromTheme('list-remove'), 'Stop and Unload Controller') elif ctrl_state == 'stopped': action_start = menu.addAction( QIcon.fromTheme('media-playback-start'), 'Start Controller') action_unload = menu.addAction( QIcon.fromTheme('list-remove'), 'Unload Controller') action = menu.exec_(self.ctrl_list_tree_widget.mapToGlobal(pos)) # evaluate user action if ctrl_state == 'running': if action is action_stop: self.start_stop_controller(ctrlman_ns, ctrl_name, False) elif action is action_kill: self.start_stop_controller(ctrlman_ns, ctrl_name, False) self.unload_controller(ctrlman_ns, ctrl_name) elif ctrl_state == 'stopped': if action is action_start: self.start_stop_controller(ctrlman_ns, ctrl_name, True) elif action is action_unload: self.unload_controller(ctrlman_ns, ctrl_name)
def __init__(self, topics): super(HistogramPlotWidget, self).__init__() self.setObjectName('HistogramPlotWidget') rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('jsk_rqt_plugins'), 'resource', 'plot_histogram.ui') loadUi(ui_file, self) self.cv_bridge = CvBridge() self.subscribe_topic_button.setIcon(QIcon.fromTheme('add')) self.pause_button.setIcon(QIcon.fromTheme('media-playback-pause')) self.clear_button.setIcon(QIcon.fromTheme('edit-clear')) self.data_plot = MatHistogramPlot(self) self.data_plot_layout.addWidget(self.data_plot) self._topic_completer = TopicCompleter(self.topic_edit) self._topic_completer.update_topics() self.topic_edit.setCompleter(self._topic_completer) self.data_plot.dropEvent = self.dropEvent self.data_plot.dragEnterEvent = self.dragEnterEvent self._start_time = rospy.get_time() self._rosdata = None if len(topics) != 0: self.subscribe_topic(topics) self._update_plot_timer = QTimer(self) self._update_plot_timer.timeout.connect(self.update_plot) self._update_plot_timer.start(self._redraw_interval)
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, parent=None): super(PublisherTreeWidget, self).__init__(parent) self.setModel(PublisherTreeModel(self)) self._action_remove_publisher = QAction(QIcon.fromTheme('list-remove'), 'Remove Selected', self) self._action_remove_publisher.triggered[bool].connect(self._handle_action_remove_publisher) self._action_publish_once = QAction(QIcon.fromTheme('media-playback-start'), 'Publish Selected Once', self) self._action_publish_once.triggered[bool].connect(self._handle_action_publish_once)
def __init__(self, parent=None): super(PublisherTreeWidget, self).__init__(parent) self.setModel(PublisherTreeModel(self)) self._action_remove_publisher = QAction(QIcon.fromTheme('list-remove'), 'Remove Selected', self) self._action_remove_publisher.triggered[bool].connect(self._handle_action_remove_publisher) self._action_publish_once = QAction(QIcon.fromTheme('media-playback-start'), 'Publish Selected Once', self) self._action_publish_once.triggered[bool].connect(self._handle_action_publish_once) self.setItemDelegateForColumn(self.model()._column_index['rate'], SpinBoxDelegate(min_value=0, max_value=1000000, decimals=2))
def _pause_resume_plots(self): if self.pause is 0: self.pause = 1 self._widget.pause_resume_plot_button.setIcon(QIcon.fromTheme('media-playback-start')) self._widget.pause_resume_plot_button.setText("Resume") else: self.pause = 0 self._widget.pause_resume_plot_button.setIcon(QIcon.fromTheme('media-playback-pause')) self._widget.pause_resume_plot_button.setText("Pause")
def __init__(self, context): super(KinestheticTeachingWidget, self).__init__() ui_file = os.path.join(rospkg.RosPack().get_path('rqt_kinesthetic_teaching'), 'resource', 'KinestheticTeaching.ui') loadUi(ui_file, self) self.setObjectName('KTeachingUi') self.setWindowTitle(self.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self) # Set icons for buttons because they don't persist frm Qt creator for some reason self.demoLocationSaveButton.setIcon(QIcon.fromTheme("document-save-as")) self.demoLocationButton.setIcon(QIcon.fromTheme("document-open")) self.demoFolderLocationButton.setIcon(QIcon.fromTheme("folder")) self.playDemoButton.setIcon(QIcon.fromTheme("media-playback-start")) # Attach event handlers self.demoLocationButton.clicked[bool].connect(self.browseForLocation) self.demoFolderLocationButton.clicked[bool].connect(self.browseForFolder) self.demoLocationSaveButton.clicked[bool].connect(self.newLocation) self.demoLocation.returnPressed.connect(self.loadLocation) self.startTrajectoryButton.clicked[bool].connect(self.startTrajectory) self.startButton.clicked[bool].connect(self.startKeyframe) self.addButton.clicked[bool].connect(self.addKeyframe) self.openHandButton.clicked[bool].connect(self.openHand) self.closeHandButton.clicked[bool].connect(self.closeHand) self.endButton.clicked[bool].connect(self.endKeyframe) self.playDemoButton.clicked[bool].connect(self.playDemo) self.enableKIBox.stateChanged.connect(self.enableKI) self.locateObjectsBox.stateChanged.connect(self.locateObjectsChanged) # Set sizing options for tree widget headers self.playbackTree.header().setStretchLastSection(False) self.playbackTree.header().setResizeMode(0, QHeaderView.Stretch) self.playbackTree.header().setResizeMode(1, QHeaderView.ResizeToContents) self.zeroMarker.setInsertPolicy(QComboBox.InsertAlphabetically) # Initialize the demonstration recorder self.kinesthetic_interaction = None try: self.kinesthetic_interaction = RQTKinestheticInteraction() print "Waiting for RQT kinesthetic interaction service" rospy.wait_for_service("kinesthetic_interaction") self.enable_kinesthetic_service = rospy.ServiceProxy("kinesthetic_interaction", KinestheticInteract) self.enable_kinesthetic_service(True) # Register callbacks self.kinesthetic_interaction.start_trajectory_cb = self.startTrajectoryCallback self.kinesthetic_interaction.start_keyframe_cb = self.startKeyframeCallback self.kinesthetic_interaction.add_keyframe_cb = self.addKeyframeCallback self.kinesthetic_interaction.end_keyframe_cb = self.endKeyframeCallback except TimeoutException as err: self._showWarning("Record keyframe demo server unreachable", str(err)) self.keyframeBagInterface = None
def __init__(self, dock_widget, qtgui_path): super(DockWidgetTitleBar, self).__init__(dock_widget) self._dock_widget = dock_widget self.hide_title_bar = False ui_file = os.path.join(qtgui_path, 'resource', 'dock_widget_title_bar.ui') loadUi(ui_file, self) self._extra_buttons = { 'configuration': self.configuration_button, 'reload': self.reload_button, 'help': self.help_button, 'close': self.close_button, } icon = QIcon.fromTheme('emblem-system') if not icon.isNull(): self.configuration_button.setIcon(icon) self.configuration_button.setText("") icon = QIcon.fromTheme('view-refresh') if not icon.isNull(): self.reload_button.setIcon(icon) self.reload_button.setText("") icon = QIcon.fromTheme('help-browser') if not icon.isNull(): self.help_button.setIcon(icon) self.help_button.setText("") icon = QIcon.fromTheme('window-close') if not icon.isNull(): self.close_button.setIcon(icon) self.close_button.setText("") self.close_button.clicked.connect(self._close_clicked) self.float_button.clicked.connect(self._toggle_floating) self.dockable_button.clicked[bool].connect(self._toggle_dockable) self.minimize_button.clicked.connect(self._minimize_dock_widget) self._dock_widget.featuresChanged.connect(self._features_changed) self._features_changed() self._update_icon() self._update_title() self._close_callbacks = [] self._event_callbacks = { QEvent.WindowIconChange: self._update_icon, QEvent.WindowTitleChange: self._update_title, } self._dock_widget.installEventFilter(self) self.title_label.installEventFilter(self) self.title_edit.hide() self.title_edit.editingFinished.connect(self._finished_editing) self.title_edit.returnPressed.connect(self._update_title_label)
def __init__(self, menu_button): QMenu.__init__(self) self.button = menu_button try: rqt_icon_path = roslib.packages.find_resource('rqt_gui', 'rqt.png').pop() menu_button.setText('') menu_button.setIcon(QIcon(rqt_icon_path)) # creates a default config menu self.action_rqt_console = QAction(QIcon.fromTheme('mail-message-new'), "&Console", self, statusTip='"<p>Starts a python GUI plugin for displaying and filtering ' 'ROS log messages that is connected to the selected master.</p>"', triggered=self.on_show_console_clicked) self.addAction(self.action_rqt_console) self.action_rqt_logger_level = QAction(QIcon.fromTheme('format-indent-more'), "&Logger Level", self, statusTip='"<p>Starts a python GUI plugin for configuring the level of ' 'ROS loggers that is connected to the selected master.</p>"', triggered=self.on_show_logger_level_clicked) self.addAction(self.action_rqt_logger_level) self.action_rqt_tf_tree = QAction(QIcon.fromTheme('preferences-system-network'), "&TF Tree", self, statusTip='"<p>Starts a python GUI plugin for visualizing the TF tree' 'that is connected to the selected master.</p>"', triggered=self.on_show_tf_tree_clicked) self.addAction(self.action_rqt_tf_tree) self.action_rqt_ros_graph = QAction(QIcon(":/icons/button_graph.png"), "Ros &Graph", self, statusTip='"<p>Starts a python GUI plugin for visualizing the ROS computation graph' 'that is connected to the selected master</p>"', triggered=self.on_show_ros_graph_clicked) self.addAction(self.action_rqt_ros_graph) self.action_rosbag_record = QAction(QIcon.fromTheme('media-record'), "rosbag record", self, statusTip='"<p>Starts the rosbag record with selected topics</p>"', triggered=self.on_start_rosbag_clicked) self.addAction(self.action_rosbag_record) self.action_rqt_rviz = QAction(QIcon.fromTheme('image-x-generic'), "R&Viz", self, statusTip='"<p>Starts RViz</p>"', triggered=self.on_show_rviz_clicked) self.addAction(self.action_rqt_rviz) self.addSeparator() self.action_rqt = QAction(QIcon(rqt_icon_path), "&Rqt GUI", self, statusTip='"<p>Start the rqt GUI' 'that is connected to the selected master</p>"', triggered=self.on_start_rqt_clicked) self.addAction(self.action_rqt) menu_button.setMenu(self) except Exception as e: print '%s' % e menu_button.setEnabled(False) menu_button.setToolTip('rqt_gui not found! Please install rqt to use its plugins!')
def __init__(self, parent=None): super(MessageTreeWidget, self).__init__(parent) self.setDragEnabled(True) self.sortByColumn(0, Qt.AscendingOrder) self.header().setResizeMode(QHeaderView.ResizeToContents) self.header().setContextMenuPolicy(Qt.CustomContextMenu) self.header().customContextMenuRequested.connect(self.handle_header_view_customContextMenuRequested) self._action_item_expand = QAction(QIcon.fromTheme('zoom-in'), 'Expand Selected', self) self._action_item_expand.triggered.connect(self._handle_action_item_expand) self._action_item_collapse = QAction(QIcon.fromTheme('zoom-out'), 'Collapse Selected', self) self._action_item_collapse.triggered.connect(self._handle_action_item_collapse) self.customContextMenuRequested.connect(self.handle_customContextMenuRequested)
def make_icon(self, image_list, mode=QIcon.Normal, state=QIcon.On): """ Helper function to create QIcons from lists of image files Warning: svg files interleaved with other files will not render correctly :param image_list: list of image paths to layer into an icon. :type image: list of str :param mode: The mode of the QIcon to be created. :type mode: int :param state: the state of the QIcon to be created. :type state: int """ if type(image_list) is not list: image_list = [image_list] if len(image_list) <= 0: raise TypeError('The list of images is empty.') num_svg = 0 for item in image_list: if item[-4:].lower() == '.svg': num_svg = num_svg + 1 if num_svg != len(image_list): # Legacy support for non-svg images icon_pixmap = QPixmap() icon_pixmap.load(image_list[0]) painter = QPainter(icon_pixmap) for item in image_list[1:]: painter.drawPixmap(0, 0, QPixmap(item)) icon = QIcon() icon.addPixmap(icon_pixmap, mode, state) painter.end() return icon else: # rendering SVG files into a QImage renderer = QSvgRenderer(image_list[0]) icon_image = QImage(renderer.defaultSize(), QImage.Format_ARGB32) icon_image.fill(0) painter = QPainter(icon_image) renderer.render(painter) if len(image_list) > 1: for item in image_list[1:]: renderer.load(item) renderer.render(painter) painter.end() # Convert QImage into a pixmap to create the icon icon_pixmap = QPixmap() icon_pixmap.convertFromImage(icon_image) icon = QIcon(icon_pixmap) return icon
def __init__(self, context): super(CapabilityGraph, self).__init__(context) self.setObjectName('CapabilityGraph') self.__current_dotcode = None self.__widget = QWidget() self.__dot_to_qt = DotToQtGenerator() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_capabilities'), 'resources', 'CapabilityGraph.ui') loadUi(ui_file, self.__widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self.__widget.setObjectName('CapabilityGraphUI') if context.serial_number() > 1: self.__widget.setWindowTitle(self.__widget.windowTitle() + (' (%d)' % context.serial_number())) self.__scene = QGraphicsScene() self.__scene.setBackgroundBrush(Qt.white) self.__widget.graphics_view.setScene(self.__scene) self.__widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh')) self.__widget.refresh_graph_push_button.pressed.connect(self.__update_capabilities_graph) self.__update_capabilities_graph() self.__deferred_fit_in_view.connect(self.__fit_in_view, Qt.QueuedConnection) self.__deferred_fit_in_view.emit() context.add_widget(self.__widget)
def __init__(self, mode=rosmsg.MODE_MSG, pkg_name='rqt_msg', ui_filename='messages.ui'): """ :param ui_filename: This Qt-based .ui file must have elements that are referred from this class. Otherwise unexpected errors are likely to happen. Best way to avoid that situation when you want to give your own .ui file is to implement all Qt components in rqt_msg/resource/message.ui file. """ super(MessagesWidget, self).__init__() self._rospack = rospkg.RosPack() ui_file = os.path.join(self._rospack.get_path(pkg_name), 'resource', ui_filename) loadUi(ui_file, self, {'MessagesTreeView': MessagesTreeView}) self.setObjectName(ui_filename) self._mode = mode self._add_button.setIcon(QIcon.fromTheme('list-add')) self._add_button.clicked.connect(self._add_message) self._refresh_packages(mode) self._refresh_msgs(self._package_combo.itemText(0)) self._package_combo.currentIndexChanged[str].connect(self._refresh_msgs) self._messages_tree.mousePressEvent = self._handle_mouse_press self._browsers = []
def __init__(self, parent = None, logger = Logger()): QWidgetWithLogger.__init__(self, parent, logger) # start widget hbox = QHBoxLayout() hbox.setMargin(0) hbox.setContentsMargins(0, 0, 0, 0) # get system icon icon = QIcon.fromTheme("view-refresh") size = icon.actualSize(QSize(32, 32)) # add combo box self.parameter_set_names_combo_box = QComboBox() self.parameter_set_names_combo_box.currentIndexChanged[str].connect(self.param_changed) hbox.addWidget(self.parameter_set_names_combo_box) # add refresh button self.get_all_parameter_set_names_button = QPushButton() self.get_all_parameter_set_names_button.clicked.connect(self._get_all_parameter_set_names) self.get_all_parameter_set_names_button.setIcon(icon) self.get_all_parameter_set_names_button.setFixedSize(size.width()+2, size.height()+2) hbox.addWidget(self.get_all_parameter_set_names_button) # end widget self.setLayout(hbox) # init widget self.reset_parameter_set_selection()
def __init__(self, topic="diagnostics"): super(RuntimeMonitorWidget, self).__init__() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_runtime_monitor'), 'resource', 'runtime_monitor_widget.ui') loadUi(ui_file, self) self.setObjectName('RuntimeMonitorWidget') self._mutex = threading.Lock() self._error_icon = QIcon.fromTheme('dialog-error') self._warning_icon = QIcon.fromTheme('dialog-warning') self._ok_icon = QIcon.fromTheme('dialog-information') self._stale_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Stale (0)']) self._stale_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._stale_node) self._error_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Errors (0)']) self._error_node.setIcon(0, self._error_icon) self.tree_widget.addTopLevelItem(self._error_node) self._warning_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Warnings (0)']) self._warning_node.setIcon(0, self._warning_icon) self.tree_widget.addTopLevelItem(self._warning_node) self._ok_node = QTreeWidgetItem(self.tree_widget.invisibleRootItem(), ['Ok (0)']) self._ok_node.setIcon(0, self._ok_icon) self.tree_widget.addTopLevelItem(self._ok_node) self.tree_widget.itemSelectionChanged.connect(self._refresh_selection) self.keyPressEvent = self._on_key_press self._name_to_item = {} self._new_errors_callback = None self._subscriber = rospy.Subscriber(topic, DiagnosticArray, self._diagnostics_callback) self._previous_ros_time = rospy.Time.now() self._timer = QTimer() self._timer.timeout.connect(self._on_timer) self._timer.start(1000) self._msg_timer = QTimer() self._msg_timer.timeout.connect(self._update_messages) self._msg_timer.start(100) self._messages = [] self._used_items = 0
def __init__(self, container_manager, serial_number): super(DockWidgetContainer, self).__init__(container_manager) self._serial_number = serial_number self._settings = None self.main_window = DockableMainWindow() self.setWidget(self.main_window) self.setWindowIcon(QIcon.fromTheme('folder'))
def get_icon(name, type_=None, base_path=None): if type_ == 'file' or type_ is None: path = name if base_path is not None: path = os.path.join(base_path, path) icon = QIcon(path) if len(icon.availableSizes()) == 0: raise UserWarning('icon "%s" not found' % str(path)) elif type_ == 'resource': icon = QIcon(name) if len(icon.availableSizes()) == 0: raise UserWarning('icon "%s" not found' % str(path)) elif type_ == 'theme': # see http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html icon = QIcon.fromTheme(name) else: raise UserWarning('unknown icon type "%s"' % str(type_)) return icon
def _show_context_menu(self, item, global_pos): if item is None: return # show context menu menu = QMenu(self) action_item_expand = menu.addAction(QIcon.fromTheme('zoom-in'), "Expand All Children") action_item_collapse = menu.addAction(QIcon.fromTheme('zoom-out'), "Collapse All Children") action = menu.exec_(global_pos) # evaluate user action if action in (action_item_expand, action_item_collapse): expanded = (action is action_item_expand) def recursive_set_expanded(item): item.setExpanded(expanded) for index in range(item.childCount()): recursive_set_expanded(item.child(index)) recursive_set_expanded(item)
def on_topics_tree_widget_customContextMenuRequested(self, pos): item = self.topics_tree_widget.itemAt(pos) if item is None: return # show context menu menu = QMenu(self) action_item_expand = menu.addAction(QIcon.fromTheme('zoom-in'), 'Expand All Children') action_item_collapse = menu.addAction(QIcon.fromTheme('zoom-out'), 'Collapse All Children') action = menu.exec_(self.topics_tree_widget.mapToGlobal(pos)) # evaluate user action if action in (action_item_expand, action_item_collapse): expanded = (action is action_item_expand) def recursive_set_expanded(item): item.setExpanded(expanded) for index in range(item.childCount()): recursive_set_expanded(item.child(index)) recursive_set_expanded(item)
def __init__(self, initial_topics=None, start_paused=False, buffer_length=100, use_poly=True, no_legend=False): super(Plot3DWidget, self).__init__() self.setObjectName('Plot3DWidget') self._buffer_length = buffer_length self._initial_topics = initial_topics rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('jsk_rqt_plugins'), 'resource', 'plot3d.ui') loadUi(ui_file, self) self.subscribe_topic_button.setIcon(QIcon.fromTheme('add')) self.remove_topic_button.setIcon(QIcon.fromTheme('remove')) self.pause_button.setIcon(QIcon.fromTheme('media-playback-pause')) self.clear_button.setIcon(QIcon.fromTheme('edit-clear')) self.data_plot = MatDataPlot3D(self, self._buffer_length, use_poly, no_legend) self.data_plot_layout.addWidget(self.data_plot) self.data_plot.autoscroll(self.autoscroll_checkbox.isChecked()) self.data_plot.dropEvent = self.dropEvent self.data_plot.dragEnterEvent = self.dragEnterEvent self.subscribe_topic_button.setEnabled(False) if start_paused: self.pause_button.setChecked(True) self._topic_completer = TopicCompleter(self.topic_edit) self._topic_completer.update_topics() self.topic_edit.setCompleter(self._topic_completer) self._start_time = rospy.get_time() self._rosdata = {} self._remove_topic_menu = QMenu() # init and start update timer for plot self._update_plot_timer = QTimer(self) self._update_plot_timer.timeout.connect(self.update_plot) if self._initial_topics: for topic_name in self._initial_topics: self.add_topic(topic_name) self._initial_topics = None
def _create_buttons(self): # create the buttons line self.buttons = QWidget(self) self.horizontalLayout = QHBoxLayout(self.buttons) self.horizontalLayout.setContentsMargins(3, 0, 3, 0) self.horizontalLayout.setObjectName("horizontalLayout") # add open upper launchfile button self.upperButton = QPushButton(self) self.upperButton.setObjectName("upperButton") self.upperButton.clicked.connect(self.on_upperButton_clicked) self.upperButton.setIcon(nm.settings().icon('up.png')) self.upperButton.setShortcut("Ctrl+U") self.upperButton.setToolTip('Open the file which include the current file (Ctrl+U)') self.upperButton.setFlat(True) self.horizontalLayout.addWidget(self.upperButton) # 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 save button self.saveButton = QPushButton(self) self.saveButton.setObjectName("saveButton") self.saveButton.setIcon(QIcon.fromTheme("document-save")) 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) # 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 show log button self.show_log_button = QPushButton("Log>>", self) self.show_log_button.setObjectName("show_log_button") self.show_log_button.clicked.connect(self.on_toggled_log) self.show_log_button.setFlat(True) self.show_log_button.setCheckable(True) self.horizontalLayout.addWidget(self.show_log_button) # add graph button self.graphButton = QPushButton(self) self.graphButton.setObjectName("graphButton") self.graphButton.toggled.connect(self.on_toggled_graph) self.graphButton.setText("Includ&e Graph >>") self.graphButton.setCheckable(True) self.graphButton.setShortcut("Ctrl+E") self.graphButton.setToolTip('Shows include and include from files (Ctrl+E)') self.graphButton.setFlat(True) self.horizontalLayout.addWidget(self.graphButton) # 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) return self.buttons
class Util(object): # TODO: Utils and common configs are mixed in this class. SECONDS_TIMELINE = 30 # Instantiating icons that show the device status. _ERR_ICON = QIcon.fromTheme('dialog-error') _WARN_ICON = QIcon.fromTheme('dialog-warning') _OK_ICON = QIcon.fromTheme('emblem-default') # Added following this QA thread http://goo.gl/83tVZ _STALE_ICON = QIcon.fromTheme('dialog-question') IMG_DICT = {0: _OK_ICON, 1: _WARN_ICON, 2: _ERR_ICON, 3: _STALE_ICON} COLOR_DICT = {0: QColor(85, 178, 76), 1: QColor(222, 213, 17), 2: QColor(178, 23, 46), 3: QColor(40, 23, 176) } # DiagnosticStatus dosn't have Stale status. Related QA:http://goo.gl/83tVZ # It's not ideal to add STALE to DiagnosticStatus as you see in that thread # but here this addition is only temporary for the purpose of # implementation simplicity. DiagnosticStatus.STALE = 3 _DICTKEY_TIMES_ERROR = 'times_errors' _DICTKEY_TIMES_WARN = 'times_warnings' _DICTKEY_INDEX = 'index' _DICTKEY_STATITEM = 'statitem' def __init__(self): super(Util, self).__init__() @staticmethod def update_status_images(diagnostic_status, statusitem): """ Taken from robot_monitor.robot_monitor_panel.py. :type status: DiagnosticStatus :type node: StatusItem :author: Isaac Saito """ name = diagnostic_status.name if (name is not None): # level = diagnosis_status.level level = diagnostic_status.level if (diagnostic_status.level != statusitem.last_level): #TODO: Apparently diagnosis_status doesn't contain last_level. statusitem.setIcon(0, Util.IMG_DICT[level]) statusitem.last_level = level return @staticmethod def get_grn_resource_name(status_name): """ :param: status_name is a string that may consists of status names that are delimited by slash. :rtype: str """ name = status_name.split('/')[-1] rospy.logdebug(' get_grn_resource_name name = %s', name) return name @staticmethod def remove_parent_name(status_name): return ('/'.join(status_name.split('/')[2:])).strip() @staticmethod def get_parent_name(status_name): return ('/'.join(status_name.split('/')[:-1])).strip() @staticmethod def gen_headline_status_green(diagnostic_status): return "%s" % Util.get_grn_resource_name(diagnostic_status.name) @staticmethod def gen_headline_warn_or_err(diagnostic_status): return "%s : %s" % (Util.get_grn_resource_name(diagnostic_status.name), diagnostic_status.message) @staticmethod def _get_color_for_message(msg, mode=0): """ :param msg: Either DiagnosticArray or DiagnosticsStatus. :param mode: int. When 0, this func will iterate msg to find DiagnosticsStatus.level and put it into a dict. When 1, this func finds DiagnosticsStatus.level from msg without iteration (thus, msg is expected to be DiagnosticsStatus instance). """ level = 0 min_level = 255 lookup = {} for status in msg.status: lookup[status.name] = status names = [status.name for status in msg.status] names = [name for name in names if len(Util.get_parent_name(name)) == 0] for name in names: status = lookup[name] if (status.level > level): level = status.level if (status.level < min_level): min_level = status.level # Stale items should be reported as errors unless all stale if (level > 2 and min_level <= 2): level = 2 # return Util.IMG_DICT[level] rospy.logdebug(' get_color_for_message color lv=%d', level) return Util.COLOR_DICT[level] @staticmethod def get_correspondent(key, list_statitem): """ :type key: String. :type list_statitem: DiagnosticsStatus :rtype: StatusItem """ names_from_list = [Util.get_grn_resource_name(status.name) for status in list_statitem] key_niced = Util.get_grn_resource_name(key) index_key = -1 statitem_key = None if key_niced in names_from_list: index_key = names_from_list.index(key_niced) statitem_key = list_statitem[index_key] rospy.logdebug(' get_correspondent index_key=%s statitem_key=%s', index_key, statitem_key) return {Util._DICTKEY_INDEX: index_key, Util._DICTKEY_STATITEM: statitem_key} @staticmethod def get_children(name, diag_array): """ :type msg: DiagnosticArray :rtype: DiagnosticStatus[] """ ret = [] for k in diag_array.status: # k is DiagnosticStatus. if k.name.startswith(name): # Starting with self.name means k # is either top/parent node / its child if not k.name == name: # Child's name must be different # from that of the top/parent node. ret.append(k) return ret
def __init__(self, context): super(ControllerManager, self).__init__(context) self.setObjectName('ControllerManager') # Create QWidget and extend it with all the attributes and children # from the UI file self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_controller_manager'), 'resource', 'controller_manager.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('ControllerManagerUi') # Pop-up that displays controller information self._popup_widget = QWidget() ui_file = os.path.join(rp.get_path('rqt_controller_manager'), 'resource', 'controller_info.ui') loadUi(ui_file, self._popup_widget) self._popup_widget.setObjectName('ControllerInfoUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) # Initialize members self._cm_ns = [] # Namespace of the selected controller manager self._controllers = [] # State of each controller self._table_model = None self._controller_lister = None # Controller manager service proxies self._load_srv = None self._unload_srv = None self._switch_srv = None # Controller state icons rospack = rospkg.RosPack() path = rospack.get_path('rqt_controller_manager') self._icons = {'running': QIcon(path + '/resource/led_green.png'), 'stopped': QIcon(path + '/resource/led_red.png'), 'uninitialized': QIcon(path + '/resource/led_off.png'), 'initialized': QIcon(path + '/resource/led_red.png')} # Controllers display table_view = self._widget.table_view table_view.setContextMenuPolicy(Qt.CustomContextMenu) table_view.customContextMenuRequested.connect(self._on_ctrl_menu) table_view.doubleClicked.connect(self._on_ctrl_info) header = table_view.horizontalHeader() header.setSectionResizeMode(QHeaderView.ResizeToContents) header.setContextMenuPolicy(Qt.CustomContextMenu) header.customContextMenuRequested.connect(self._on_header_menu) # Timer for controller manager updates self._list_cm = ControllerManagerLister() self._update_cm_list_timer = QTimer(self) self._update_cm_list_timer.setInterval(1000.0 / self._cm_update_freq) self._update_cm_list_timer.timeout.connect(self._update_cm_list) self._update_cm_list_timer.start() # Timer for running controller updates self._update_ctrl_list_timer = QTimer(self) self._update_ctrl_list_timer.setInterval(1000.0 / self._cm_update_freq) self._update_ctrl_list_timer.timeout.connect(self._update_controllers) self._update_ctrl_list_timer.start() # Signal connections w = self._widget w.cm_combo.currentIndexChanged[str].connect(self._on_cm_change)
def _on_wait_for_publishing(self): self.updateIconView(QIcon(':/icons/state_off.png'))
def __check_icon_theme_compliance(self): from python_qt_binding.QtGui import QIcon # TODO find a better way to verify Theme standard compliance if QIcon.themeName() == '' or \ QIcon.fromTheme('document-save').isNull() or \ QIcon.fromTheme('document-open').isNull() or \ QIcon.fromTheme('edit-cut').isNull() or \ QIcon.fromTheme('object-flip-horizontal').isNull(): original_theme = QIcon.themeName() QIcon.setThemeName('Tango') if QIcon.fromTheme('document-save').isNull(): QIcon.setThemeName(original_theme)
def __init__(self, context): super(RosBehaviourTree, self).__init__(context) self.setObjectName('RosBehaviourTree') parser = argparse.ArgumentParser() RosBehaviourTree.add_arguments(parser, False) # if the context doesn't have an argv attribute then assume we're running with --no-roscore if not hasattr(context, 'argv'): args = sys.argv[1:] # Can run the viewer with or without live updating. Running without is # intended for viewing of bags only self.live_update = False else: args = context.argv() self.live_update = True parsed_args = parser.parse_args(args) self.context = context self.initialized = False self._current_dotcode = None # dotcode for the tree that is currently displayed self._viewing_bag = False # true if a bag file is loaded # True if next or previous buttons are pressed. Reset if the tree being # viewed is the last one in the list. self._browsing_timeline = False self._widget = QWidget() # factory builds generic dotcode items self.dotcode_factory = PygraphvizFactory() # PydotFactory() # self.dotcode_factory = PygraphvizFactory() # generator builds rosgraph self.dotcode_generator = RosBehaviourTreeDotcodeGenerator() self.current_topic = None self.behaviour_sub = None self._tip_message = None # message of the tip of the tree self._default_topic = parsed_args.topic # topic parsed on the command line self._saved_settings_topic = None # topic subscribed to by previous instance self.visibility_level = py_trees.common.VisibilityLevel.DETAIL # dot_to_qt transforms into Qt elements using dot layout self.dot_to_qt = DotToQtGenerator() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_py_trees'), 'resource', 'RosBehaviourTree.ui') loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self._widget.setObjectName('RosBehaviourTreeUi') if hasattr(context, 'serial_number') and context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) self._widget.highlight_connections_check_box.toggled.connect( self._redraw_graph_view) self._widget.auto_fit_graph_check_box.toggled.connect( self._redraw_graph_view) self._widget.fit_in_view_push_button.setIcon( QIcon.fromTheme('zoom-original')) self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view) self._widget.load_bag_push_button.setIcon( QIcon.fromTheme('document-open')) self._widget.load_bag_push_button.pressed.connect(self._load_bag) self._widget.load_dot_push_button.setIcon( QIcon.fromTheme('document-open')) self._widget.load_dot_push_button.pressed.connect(self._load_dot) self._widget.save_dot_push_button.setIcon( QIcon.fromTheme('document-save-as')) self._widget.save_dot_push_button.pressed.connect(self._save_dot) self._widget.save_as_svg_push_button.setIcon( QIcon.fromTheme('document-save-as')) self._widget.save_as_svg_push_button.pressed.connect(self._save_svg) self._widget.save_as_image_push_button.setIcon( QIcon.fromTheme('image')) self._widget.save_as_image_push_button.pressed.connect( self._save_image) for text in visibility.combo_to_py_trees: self._widget.visibility_level_combo_box.addItem(text) self._widget.visibility_level_combo_box.setCurrentIndex( self.visibility_level) self._widget.visibility_level_combo_box.currentIndexChanged[ 'QString'].connect(self._update_visibility_level) # set up the function that is called whenever the box is resized - # ensures that the timeline is correctly drawn. self._widget.resizeEvent = self._resize_event self._timeline = None self._timeline_listener = None # Connect the message changed function of this object to a corresponding # signal. This signal will be activated whenever the message being # viewed changes. self._message_changed.connect(self.message_changed) self._message_cleared.connect(self.message_cleared) # Set up combo box for topic selection # when the refresh_combo signal happens, update the combo topics available self._refresh_combo.connect(self._update_combo_topics) # filter events to catch the event which opens the combo box self._combo_event_filter = RosBehaviourTree.ComboBoxEventFilter( self._refresh_combo) self._widget.topic_combo_box.installEventFilter( self._combo_event_filter) self._widget.topic_combo_box.activated.connect(self._choose_topic) # Delay populating the combobox, let restore_settings() handle it # self._update_combo_topics() # Set up navigation buttons self._widget.previous_tool_button.pressed.connect(self._previous) self._widget.previous_tool_button.setIcon( QIcon.fromTheme('go-previous')) self._widget.next_tool_button.pressed.connect(self._next) self._widget.next_tool_button.setIcon(QIcon.fromTheme('go-next')) self._widget.first_tool_button.pressed.connect(self._first) self._widget.first_tool_button.setIcon(QIcon.fromTheme('go-first')) self._widget.last_tool_button.pressed.connect(self._last) self._widget.last_tool_button.setIcon(QIcon.fromTheme('go-last')) # play, pause and stop buttons self._widget.play_tool_button.pressed.connect(self._play) self._widget.play_tool_button.setIcon( QIcon.fromTheme('media-playback-start')) self._widget.stop_tool_button.pressed.connect(self._stop) self._widget.stop_tool_button.setIcon( QIcon.fromTheme('media-playback-stop')) # also connect the navigation buttons so that they stop the timer when # pressed while the tree is playing. self._widget.first_tool_button.pressed.connect(self._stop) self._widget.previous_tool_button.pressed.connect(self._stop) self._widget.last_tool_button.pressed.connect(self._stop) self._widget.next_tool_button.pressed.connect(self._stop) # set up shortcuts for navigation (vim) next_shortcut_vi = QShortcut(QKeySequence("l"), self._widget) next_shortcut_vi.activated.connect( self._widget.next_tool_button.pressed) previous_shortcut_vi = QShortcut(QKeySequence("h"), self._widget) previous_shortcut_vi.activated.connect( self._widget.previous_tool_button.pressed) first_shortcut_vi = QShortcut(QKeySequence("^"), self._widget) first_shortcut_vi.activated.connect( self._widget.first_tool_button.pressed) last_shortcut_vi = QShortcut(QKeySequence("$"), self._widget) last_shortcut_vi.activated.connect( self._widget.last_tool_button.pressed) # shortcuts for emacs next_shortcut_emacs = QShortcut(QKeySequence("Ctrl+f"), self._widget) next_shortcut_emacs.activated.connect( self._widget.next_tool_button.pressed) previous_shortcut_emacs = QShortcut(QKeySequence("Ctrl+b"), self._widget) previous_shortcut_emacs.activated.connect( self._widget.previous_tool_button.pressed) first_shortcut_emacs = QShortcut(QKeySequence("Ctrl+a"), self._widget) first_shortcut_emacs.activated.connect( self._widget.first_tool_button.pressed) last_shortcut_emacs = QShortcut(QKeySequence("Ctrl+e"), self._widget) last_shortcut_emacs.activated.connect( self._widget.last_tool_button.pressed) # set up stuff for dotcode cache self._dotcode_cache_capacity = 50 self._dotcode_cache = {} # cache is ordered on timestamps from messages, but earliest timestamp # isn't necessarily the message that was viewed the longest time ago, so # need to store keys self._dotcode_cache_keys = [] # set up stuff for scene cache (dotcode cache doesn't seem to make much difference) self._scene_cache_capacity = 50 self._scene_cache = {} self._scene_cache_keys = [] # Update the timeline buttons to correspond with a completely # uninitialised state. self._set_timeline_buttons(first_snapshot=False, previous_snapshot=False, next_snapshot=False, last_snapshot=False) self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() # This is used to store a timer which controls how fast updates happen when the play button is pressed. self._play_timer = None # updates the view self._refresh_view.connect(self._refresh_tree_graph) self._force_refresh = False if self.live_update: context.add_widget(self._widget) else: self.initialized = True # this needs to be set for trees to be displayed context.setCentralWidget(self._widget) if parsed_args.bag: self._load_bag(parsed_args.bag) elif parsed_args.latest_bag: # if the latest bag is requested, load it from the default directory, or # the one specified in the args bag_dir = parsed_args.bag_dir or os.getenv( 'ROS_HOME', os.path.expanduser('~/.ros')) + '/behaviour_trees' self.open_latest_bag(bag_dir, parsed_args.by_time)
def __init__(self, context): super(MyPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MyPlugin') rp = rospkg.RosPack() # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which is a sibling of this file # in this example the .ui and .py file are in the same folder ui_file = os.path.join(rp.get_path('rqt_sosvr_controller'), 'resource', 'MyPlugin.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('MyPluginUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface robot_names = ['sos1', 'sos2', 'sos3', 'sos4'] self._widget.robot_box.addItems(robot_names) self._widget.controlUp.setIcon(QIcon.fromTheme('up')) self._widget.controlBottom.setIcon(QIcon.fromTheme('down')) self._widget.controlRight.setIcon(QIcon.fromTheme('next')) self._widget.controlLeft.setIcon(QIcon.fromTheme('back')) self._widget.auto1.stateChanged.connect(lambda:self.setAuto('1')) self._widget.auto2.stateChanged.connect(lambda:self.setAuto('2')) self._widget.auto3.stateChanged.connect(lambda:self.setAuto('3')) self._widget.auto4.stateChanged.connect(lambda:self.setAuto('4')) self._widget.buttonOn.setIcon(QIcon.fromTheme('player_play')) self._widget.buttonOff.setIcon(QIcon.fromTheme('gtk-stop')) self._widget.controlUp.clicked.connect(self.controlSignalUp) # 1 Up self._widget.controlRight.clicked.connect(self.controlSignalRight) # 2 Right self._widget.controlBottom.clicked.connect(self.controlSignalBottom) # 3 Bottom self._widget.controlLeft.clicked.connect(self.controlSignalLeft) # 4 Down self.drive_mode=rospy.Publisher("drive_mode",String,queue_size=10) self._widget.buttonOn.clicked.connect(self.turnRobotOn) self._widget.buttonOff.clicked.connect(self.turnRobotOff) a1 = rospy.Publisher("/sos1/move_base/cancel", GoalID, queue_size=10) a2 = rospy.Publisher("/sos2/move_base/cancel", GoalID, queue_size=10) a3 = rospy.Publisher("/sos3/move_base/cancel", GoalID, queue_size=10) a4 = rospy.Publisher("/sos4/move_base/cancel", GoalID, queue_size=10) ss_pub1 = rospy.Publisher('sos1/cmd_vel', Twist, queue_size=10) ss_pub2 = rospy.Publisher('sos2/cmd_vel', Twist, queue_size=10) ss_pub3 = rospy.Publisher('sos3/cmd_vel', Twist, queue_size=10) ss_pub4 = rospy.Publisher('sos4/cmd_vel', Twist, queue_size=10) self._pubs = [ss_pub1, ss_pub2, ss_pub3, ss_pub4] self._holds= [a1, a2, a3, a4] context.add_widget(self._widget) self.subscribeToJoy()
def _publish_finished(self): self._publish_thread = None self.setIcon(QIcon())
def _instantiate_tl_icon(self): timeline_marker_icon = QIcon.fromTheme('system-search') timeline_marker_icon_pixmap = timeline_marker_icon.pixmap( self._timeline_marker_width, self._timeline_marker_height) return QGraphicsPixmapItem(timeline_marker_icon_pixmap)
def __init__(self, parent=None): ''' Creates the window, connects the signals and init the class. ''' QDockWidget.__init__(self, parent) # initialize parameter self.__current_path = os.path.expanduser('~') # load the UI file ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'LaunchFilesDockWidget.ui') loadUi(ui_file, self, custom_widgets={'EnhancedLineEdit': EnhancedLineEdit}) self._current_search = '' pal = self.palette() self._default_color = pal.color(QPalette.Window) # initialize the progress queue self.progress_queue = ProgressQueue(self.ui_frame_progress_cfg, self.ui_bar_progress_cfg, self.ui_button_progress_cancel_cfg, 'Launch File') # initialize the view for the launch files self.launchlist_model = LaunchListModel( progress_queue=self.progress_queue, viewobj=self.ui_file_view) self.launchlist_proxy_model = QSortFilterProxyModel(self) self.launchlist_proxy_model.setSourceModel(self.launchlist_model) self.name_delegate = HTMLDelegate(check_for_ros_names=False, palette=self.palette()) self.ui_file_view.setItemDelegateForColumn(0, self.name_delegate) self.ui_file_view.setModel(self.launchlist_proxy_model) self.ui_file_view.setAlternatingRowColors(True) self.ui_file_view.activated.connect(self.on_launch_selection_activated) self.ui_file_view.setDragDropMode(QAbstractItemView.DragOnly) self.ui_file_view.setDragEnabled(True) sm = self.ui_file_view.selectionModel() sm.selectionChanged.connect(self.on_ui_file_view_selection_changed) self.launchlist_model.pathlist_handled.connect( self.on_pathlist_handled) self.launchlist_model.error_on_path.connect(self.on_error_on_path) self.ui_search_line.refresh_signal.connect(self.set_package_filter) self.ui_search_line.stop_signal.connect(self.stop) # connect to the button signals self.ui_button_reload.clicked.connect(self.on_reload_clicked) self.ui_button_edit.clicked.connect(self.on_edit_xml_clicked) #self.ui_button_new.clicked.connect(self.on_new_xml_clicked) self.ui_button_transfer.clicked.connect(self.on_transfer_file_clicked) self.ui_button_save_profile.clicked.connect( self.on_save_profile_clicked) self.ui_button_load.clicked.connect(self.on_load_xml_clicked) # add menu to create fiel or directory self._menu_add = QMenu() create_file_action = QAction( QIcon(':/icons/crystal_clear_launch_file_new.png'), "create file", self, statusTip="", triggered=self.on_new_xml_clicked) create_dir_action = QAction(QIcon(':/icons/crystal_clear_folder.png'), "create directory", self, statusTip="", triggered=self.on_new_dir_clicked) self._menu_add.addAction(create_file_action) self._menu_add.addAction(create_dir_action) self.ui_button_new.setMenu(self._menu_add) self._masteruri2name = {} self._reload_timer = None
def _check_icon_theme_compliance(self): from python_qt_binding.QtGui import QIcon # TODO find a better way to verify Theme standard compliance if QIcon.themeName() == '' or \ QIcon.fromTheme('document-save').isNull() or \ QIcon.fromTheme('document-open').isNull() or \ QIcon.fromTheme('edit-cut').isNull() or \ QIcon.fromTheme('object-flip-horizontal').isNull(): if 'darwin' in platform.platform().lower( ) and '/usr/local/share/icons' not in QIcon.themeSearchPaths(): QIcon.setThemeSearchPaths(QIcon.themeSearchPaths() + ['/usr/local/share/icons']) original_theme = QIcon.themeName() QIcon.setThemeName('Tango') if QIcon.fromTheme('document-save').isNull(): QIcon.setThemeName(original_theme)
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. # rp = rospkg.RosPack() # ui_file = os.path.join(rp.get_path('rqt_reconfigure'), # 'resource', 'singlenode_parameditor.ui') # loadUi(ui_file, self) verticalLayout = QVBoxLayout(self) _widget_nodeheader = QWidget() _h_layout_nodeheader = QHBoxLayout(_widget_nodeheader) 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, filenames, search_text='', master_name='', parent=None): ''' :param filenames: a list with filenames. The last one will be activated. :type filenames: [str] :param str search_text: if not empty, searches in new document for first occurrence of the given text ''' QMainWindow.__init__(self, parent) self.setObjectName('Editor - %s' % utf8(filenames)) self.setAttribute(Qt.WA_DeleteOnClose, True) self.setWindowFlags(Qt.Window) self.mIcon = nm.settings().icon('crystal_clear_edit_launch.png') self._error_icon = nm.settings().icon('warning.png') self._info_icon = nm.settings().icon('info.png') self._empty_icon = QIcon() self.setWindowIcon(self.mIcon) window_title = "ROSLaunch Editor" if filenames: window_title = self.__getTabName(filenames[0]) self.setWindowTitle('%s @%s' % (window_title, master_name)) self.init_filenames = filenames self._search_node_count = 0 self._search_thread = None self._last_search_request = None # list with all open files self.files = [] # create tabs for files self.main_widget = QWidget(self) self.main_widget.setObjectName("editorMain") 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.tabWidget.currentChanged.connect(self.on_tab_changed) self.verticalLayout.addWidget(self.tabWidget) self.log_dock = self._create_log_bar() self.addDockWidget(Qt.BottomDockWidgetArea, self.log_dock) # self.verticalLayout.addWidget(self.log_bar) 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.found_signal.connect(self.on_search_result) self.find_dialog.replace_signal.connect(self.on_replace) self.addDockWidget(Qt.RightDockWidgetArea, self.find_dialog) self.graph_view = GraphViewWidget(self.tabWidget, self) self.graph_view.load_signal.connect(self.on_graph_load_file) self.graph_view.goto_signal.connect(self.on_graph_goto) self.graph_view.search_signal.connect(self.on_load_request) self.graph_view.finished_signal.connect(self.on_graph_finished) self.graph_view.info_signal.connect(self.on_graph_info) self.addDockWidget(Qt.RightDockWidgetArea, self.graph_view) self.readSettings() self.find_dialog.setVisible(False) self.graph_view.setVisible(False) nm.nmd().file.changed_file.connect(self.on_changed_file) nm.nmd().file.packages_available.connect(self._on_new_packages) # open the files for f in filenames: if f: self.on_load_request(f, search_text, only_launch=True) self.log_dock.setVisible(False) try: pal = self.tabWidget.palette() self._default_color = pal.color(QPalette.Window) color = QColor.fromRgb(nm.settings().host_color(master_name, self._default_color.rgb())) bg_style_launch_dock = "QWidget#editorMain { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 %s, stop: 0.7 %s);}" % (color.name(), self._default_color.name()) self.setStyleSheet('%s' % (bg_style_launch_dock)) except Exception as _: pass
def __init__(self, context): super(TelloPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('TelloPlugin') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print('arguments: ', args) print('unknowns: ', unknowns) # load main widget self._widget = QWidget() self.ui = Ui_TelloPlugin() self.ui.setupUi(self._widget) self.ui.tabWidget.setCurrentIndex(0) self._widget.setObjectName('TelloPluginUi') # Add left and right key arrow blocking filter = KeySuppress() self.ui.tabWidget.installEventFilter(filter) if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) print("Tello widget added") # Tello node self.bridge = CvBridge() self.pos_listener = TransformListener() # Add recorder and Recording Timer self.recording = False self.record_timer = QTimer() self.record_timer.timeout.connect(self.update_record_time) self.record_time = QTime(00,00,00) self.video_recorder = None self.VIDEO_TYPE = {'avi': cv2.VideoWriter_fourcc(*'XVID'), 'mp4': cv2.VideoWriter_fourcc(*'MP4V')} # System, process and Wifi interface info interface = "wlp2s0" ssid_names = "TELLO-FD143A" self.wifi_info = WifiInfo(interface, ssid_names) self.utility = GetUtility() # Callbacks GUI items self.ui.connect_button.clicked[bool].connect(self.handle_connect_clicked) self.ui.record_button.clicked[bool].connect(self.handle_record_clicked) self.ui.foto_button.clicked[bool].connect(self.handle_foto_clicked) self.ui.stop_button.clicked[bool].connect(self.handle_stop_clicked) self.ui.start_button.clicked[bool].connect(self.handle_start_clicked) self.ui.land_button.clicked[bool].connect(self.handle_land_clicked) self.ui.target_button.clicked[bool].connect(self.handle_target_clicked) self.ui.calibrate_button.clicked[bool].connect(self.handle_calibrate_clicked) # Set icons # get an instance of RosPack with the default search paths rospack = rospkg.RosPack() icon_path = rospack.get_path('tello_rqt_gui') + '/src/tello_rqt/resource/icons/' self.ui.record_button.setText('') # override text with icon self.ui.record_button.setIcon(QIcon(QPixmap(icon_path + 'video.png'))) self.ui.record_button.setIconSize(QSize(25,25)) self.ui.foto_button.setText('') # override text with icon self.ui.foto_button.setIcon(QIcon(QPixmap(icon_path + 'foto.png'))) self.ui.foto_button.setIconSize(QSize(25,25)) self.ui.label_record_time.setText('record') # Set bar values to 0 self.ui.link_bar.setValue(0) self.ui.battery_bar.setValue(0) self.ui.cpu_bar.setValue(0) self.ui.memory_bar.setValue(0) self.ui.temperature_bar.setValue(0) # create signals and slots for updates # never access widgets and GUI related things directly from a thread other than the main thread self.sig_connection_changed.connect(self.update_ui_state) self.sig_update_position.connect(self.update_position_data) self.sig_battery_percentage.connect(self.ui.battery_bar.setValue) self.sig_tello_link.connect(self.ui.link_bar.setValue) self.sig_wifi_sig_link.connect(self.ui.wifi_signal_bar.setValue) self.sig_cpu.connect(self.ui.cpu_bar.setValue) self.sig_memory.connect(self.ui.memory_bar.setValue) self.sig_temperature.connect(self.ui.temperature_bar.setValue) self.sig_height.connect(self.ui.label_height.setText) self.sig_speed.connect(self.ui.label_speed.setText) self.sig_flight_time.connect(self.ui.label_flight_time.setText) self.sig_image.connect(self.set_image) self.sig_battery_low.connect(self.ui.label_battery_low.setText) self.sig_is_flying.connect(self.ui.label_is_flying.setText) self.sig_fly_mode.connect(self.ui.label_fly_mode.setText) self.sig_fast_mode.connect(self.ui.label_fast_mode.setText) self.sig_remaining_time.connect(self.ui.label_remaining_time.setText) self.sig_foto_info.connect(self.ui.label_foto.setText) #self.sig_mission_state.connect(self.ui.label_mission_state.setText) # Connect signals from Tello, Controller und SLAM to GUI self.ns_tello = 'tello/' self.ns_controller = 'tello_controller/' self.topic_slam_pose = '/orb_slam2_mono/pose' self.topic_slam_scale = 'tello_controller/slam_real_world_scale' self.tello_state = self.STATE_DISCONNECTED.getname() self.pub_connect = rospy.Publisher(self.ns_tello+'connect', Empty, queue_size=1, latch=True) self.pub_disconnect = rospy.Publisher(self.ns_tello+'disconnect', Empty, queue_size=1, latch=True) self.pub_take_picture = rospy.Publisher(self.ns_tello+'take_picture', Empty, queue_size=1, latch=True) self.pub_mission_command = rospy.Publisher(self.ns_controller+'mission_command', String, queue_size=1, latch=True) self.sub_picture_update = rospy.Subscriber(self.ns_tello+'picture_update', String, self.cb_picture_update) self.sub_status = rospy.Subscriber(self.ns_tello+'status', TelloStatus, self.cb_status) self.sub_connection = rospy.Subscriber(self.ns_tello+'connection_state', String, self.cb_connection) self.sub_video = rospy.Subscriber('tello/camera/image_raw', Image, self.cb_video) self.sub_odom = rospy.Subscriber(self.ns_tello+'odom', Odometry, self.cb_odom, queue_size=1) self.sub_slam_pose = rospy.Subscriber(self.topic_slam_pose, PoseStamped, self.cb_slam_pose, queue_size=1) self.sub_slam_scale = rospy.Subscriber(self.topic_slam_scale, Float32, self.cb_slam_scale, queue_size=1) self.sub_mission = rospy.Subscriber(self.ns_controller+'mission_state', String, self.cb_mission_state) self.cv_image = None # create additional thread for system und process utility self.stop_threads = False self.thread = threading.Thread(target=self.update_sys_util, args=()) self.thread.start() print('init done')
def __init__(self, proxy_model, rospack, minimal=False): """ :param proxymodel: the proxy model to display in the widget,''QSortFilterProxyModel'' :param minimal: if true the load, save and column buttons will be hidden as well as the filter splitter, ''bool'' """ super(ConsoleWidget, self).__init__() self._proxy_model = proxy_model self._model = self._proxy_model.sourceModel() self._paused = False self._rospack = rospack # These are lists of Tuples = (,) self._exclude_filters = [] self._highlight_filters = [] ui_file = os.path.join(self._rospack.get_path('rqt_console'), 'resource', 'console_widget.ui') loadUi(ui_file, self) if minimal: self.load_button.hide() self.save_button.hide() self.column_resize_button.hide() self.setObjectName('ConsoleWidget') self.table_view.setModel(proxy_model) self._columnwidth = (60, 100, 70, 100, 100, 100, 100) for idx, width in enumerate(self._columnwidth): self.table_view.horizontalHeader().resizeSection(idx, width) try: setSectionResizeMode = self.table_view.horizontalHeader( ).setSectionResizeMode # Qt5 except AttributeError: setSectionResizeMode = self.table_view.horizontalHeader( ).setResizeMode # Qt4 setSectionResizeMode(1, QHeaderView.Stretch) def update_sort_indicator(logical_index, order): if logical_index == 0: self._proxy_model.sort(-1) self.table_view.horizontalHeader().setSortIndicatorShown( logical_index != 0) self.table_view.horizontalHeader().sortIndicatorChanged.connect( update_sort_indicator) self.add_exclude_button.setIcon(QIcon.fromTheme('list-add')) self.add_highlight_button.setIcon(QIcon.fromTheme('list-add')) self.pause_button.setIcon(QIcon.fromTheme('media-playback-pause')) if not self.pause_button.icon().isNull(): self.pause_button.setText('') self.record_button.setIcon(QIcon.fromTheme('media-record')) if not self.record_button.icon().isNull(): self.record_button.setText('') self.load_button.setIcon(QIcon.fromTheme('document-open')) if not self.load_button.icon().isNull(): self.load_button.setText('') self.save_button.setIcon(QIcon.fromTheme('document-save')) if not self.save_button.icon().isNull(): self.save_button.setText('') self.clear_button.setIcon(QIcon.fromTheme('edit-clear')) if not self.clear_button.icon().isNull(): self.clear_button.setText('') self.highlight_exclude_button.setIcon( QIcon.fromTheme('format-text-strikethrough')) self.pause_button.clicked[bool].connect(self._handle_pause_clicked) self.record_button.clicked[bool].connect(self._handle_record_clicked) self.load_button.clicked[bool].connect(self._handle_load_clicked) self.save_button.clicked[bool].connect(self._handle_save_clicked) self.column_resize_button.clicked[bool].connect( self._handle_column_resize_clicked) self.clear_button.clicked[bool].connect( self._handle_clear_button_clicked) self.table_view.mouseDoubleClickEvent = self._handle_mouse_double_click self.table_view.mousePressEvent = self._handle_mouse_press self.table_view.keyPressEvent = self._handle_custom_keypress self.highlight_exclude_button.clicked[bool].connect( self._proxy_model.set_show_highlighted_only) self.add_highlight_button.clicked.connect(self._add_highlight_filter) self.add_exclude_button.clicked.connect(self._add_exclude_filter) # Filter factory dictionary: # index 0 is a label describing the widget, index 1 is the class that provides filtering logic # index 2 is the widget that sets the data in the filter class, index 3 are the arguments for the widget class constructor self._filter_factory_order = [ 'message', 'severity', 'node', 'time', 'topic', 'location', 'custom' ] self.filter_factory = { 'message': (self.tr('...containing'), MessageFilter, TextFilterWidget), 'severity': (self.tr('...with severities'), SeverityFilter, ListFilterWidget, self._model.get_severity_dict), 'node': (self.tr('...from node'), NodeFilter, ListFilterWidget, self._model.get_unique_nodes), 'time': (self.tr('...from time range'), TimeFilter, TimeFilterWidget, self.get_time_range_from_selection), 'topic': (self.tr('...from topic'), TopicFilter, ListFilterWidget, self._model.get_unique_topics), 'location': (self.tr('...from location'), LocationFilter, TextFilterWidget), 'custom': (self.tr('Custom'), CustomFilter, CustomFilterWidget, [ self._model.get_severity_dict, self._model.get_unique_nodes, self._model.get_unique_topics ]) } self._model.rowsInserted.connect(self.update_status) self._model.rowsRemoved.connect(self.update_status) self._proxy_model.rowsInserted.connect(self.update_status) self._proxy_model.rowsRemoved.connect(self.update_status) # list of TextBrowserDialogs to close when cleaning up self._browsers = [] # This defaults the filters panel to start by taking 50% of the available space if minimal: self.table_splitter.setSizes([1, 0]) else: self.table_splitter.setSizes([1, 1]) self.exclude_table.resizeColumnsToContents() self.highlight_table.resizeColumnsToContents()
def get_icon(self): return QIcon()
def icon(self, name): return QIcon(self.icon_path(name))
def __init__(self, context): super(HandEyeCalibration, self).__init__(context) self.context = context self.node = context.node self.widget = QWidget() self.widget.setObjectName(self.PLUGIN_TITLE) self.widget.setWindowTitle(self.PLUGIN_TITLE) # Data self.Tsamples = [] # Toolbar _, path_pkg = get_resource('packages', 'handeye_dashboard') print("{}".format(path_pkg)) self.snapshot_action = QAction(QIcon.fromTheme('camera-photo'), 'Take a snapshot', self.widget) path = path_pkg + '/share/handeye_dashboard/images/capture.png' self.calibrate_action = QAction(QIcon(QPixmap.fromImage(QImage(path))), 'Get the camera/robot transform', self.widget) self.clear_action = QAction(QIcon.fromTheme('edit-clear'), 'Clear the record data.', self.widget) path = path_pkg + '/share/handeye_dashboard/images/UR5.png' self.execut_action = QAction(QIcon(QPixmap.fromImage(QImage(path))), 'EStart the publishing the TF.', self.widget) self.toolbar = QToolBar() self.toolbar.addAction(self.snapshot_action) self.toolbar.addAction(self.calibrate_action) self.toolbar.addAction(self.clear_action) self.toolbar.addAction(self.execut_action) # Toolbar0 self.l0 = QLabel(self.widget) self.l0.setText("Camera-Mount-Type: ") self.l0.setFixedWidth(150) self.l0.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.combobox = QComboBox(self.widget) self.combobox.addItem('attached on robot') self.combobox.addItem('fixed beside robot') self.toolbar0 = QToolBar() self.toolbar0.addWidget(self.l0) self.toolbar0.addWidget(self.combobox) # Toolbar1 self.l1 = QLabel(self.widget) self.l1.setText("Camera-Frame: ") self.l1.setFixedWidth(150) self.l1.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.camera_frame = QLineEdit(self.widget) self.camera_frame.setText("camera_link") self.toolbar1 = QToolBar() self.toolbar1.addWidget(self.l1) self.toolbar1.addWidget(self.camera_frame) # Toolbar2 self.l2 = QLabel(self.widget) self.l2.setText("Object-Frame: ") self.l2.setFixedWidth(150) self.l2.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.object_frame = QLineEdit(self.widget) self.object_frame.setText("calib_board") self.toolbar2 = QToolBar() self.toolbar2.addWidget(self.l2) self.toolbar2.addWidget(self.object_frame) # Toolbar3 self.l3 = QLabel(self.widget) self.l3.setText("Robot-Base-Frame: ") self.l3.setFixedWidth(150) self.l3.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.base_frame = QLineEdit(self.widget) self.base_frame.setText("base") self.toolbar3 = QToolBar() self.toolbar3.addWidget(self.l3) self.toolbar3.addWidget(self.base_frame) # Toolbar4 self.l4 = QLabel(self.widget) self.l4.setText("End-Effector-Frame: ") self.l4.setFixedWidth(150) self.l4.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.endeffector_frame = QLineEdit(self.widget) self.endeffector_frame.setText("tool0") self.toolbar4 = QToolBar() self.toolbar4.addWidget(self.l4) self.toolbar4.addWidget(self.endeffector_frame) # Toolbar5 self.l5 = QLabel(self.widget) self.l5.setText("Sample-Number: ") self.l5.setFixedWidth(150) self.l5.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter) self.le5 = QLineEdit(self.widget) self.le5.setValidator(QIntValidator()) self.le5.setText('10') self.le5.setReadOnly(True) self.toolbar5 = QToolBar() self.toolbar5.addWidget(self.l5) self.toolbar5.addWidget(self.le5) # TreeView self.treeview = QTreeView() self.treeview.setAlternatingRowColors(True) self.model = QStandardItemModel(self.treeview) self.treeview.setModel(self.model) self.treeview.setHeaderHidden(True) # TextEdit self.textedit = QTextEdit(self.widget) self.textedit.setReadOnly(True) # Layout self.layout = QVBoxLayout() self.layout.addWidget(self.toolbar0) self.layout.addWidget(self.toolbar1) self.layout.addWidget(self.toolbar2) self.layout.addWidget(self.toolbar3) self.layout.addWidget(self.toolbar4) self.layout.addWidget(self.toolbar5) self.layout.addWidget(self.toolbar) self.layoutH = QHBoxLayout() self.layoutH.addWidget(self.treeview) self.layoutH.addWidget(self.textedit) self.layout.addLayout(self.layoutH) self.widget.setLayout(self.layout) # Add the widget to the user interface if context.serial_number() > 1: self.widget.setWindowTitle(self.widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self.widget) # Make the connections self.snapshot_action.triggered.connect(self.take_snapshot) self.calibrate_action.triggered.connect(self.calibration) self.clear_action.triggered.connect(self.clear) self.execut_action.triggered.connect(self.execution) # Package path self.path_pkg = path_pkg # Set up TF self.cli = self.node.create_client(HandeyeTF, 'handeye_tf_service') while not self.cli.wait_for_service(timeout_sec=1.0): self.node.get_logger().info( 'service not available, waiting again...') self.req = HandeyeTF.Request()
def main(self, argv=None, standalone=None): # check if DBus is available try: import dbus del dbus self._dbus_available = True except ImportError: pass if argv is None: argv = sys.argv # extract --args and everything behind manually since argparse can not handle that arguments = argv[1:] args = [] if '--args' in arguments: index = arguments.index('--args') args = arguments[index + 1:] arguments = arguments[0:index + 1] if standalone: arguments += ['-s', standalone] parser = ArgumentParser('usage: %prog [options]') self._add_arguments(parser) self._options = parser.parse_args(arguments) self._options.args = args # check option dependencies try: if self._options.args and not self._options.standalone_plugin and not self._options.command_start_plugin and not self._options.embed_plugin: raise RuntimeError( 'Option --args can only be used together with either --standalone, --command-start-plugin or --embed-plugin option' ) list_options = (self._options.list_perspectives, self._options.list_plugins) list_options_set = [ opt for opt in list_options if opt is not False ] if len(list_options_set) > 1: raise RuntimeError( 'Only one --list-* option can be used at a time') command_options = (self._options.command_start_plugin, self._options.command_switch_perspective) command_options_set = [ opt for opt in command_options if opt is not None ] if len(command_options_set) > 0 and not self._dbus_available: raise RuntimeError( 'Without DBus support the --command-* options are not available' ) if len(command_options_set) > 1: raise RuntimeError( 'Only one --command-* option can be used at a time (except --command-pid which is optional)' ) if len(command_options_set ) == 0 and self._options.command_pid is not None: raise RuntimeError( 'Option --command_pid can only be used together with an other --command-* option' ) embed_options = (self._options.embed_plugin, self._options.embed_plugin_serial, self._options.embed_plugin_address) embed_options_set = [ opt for opt in embed_options if opt is not None ] if len(command_options_set) > 0 and not self._dbus_available: raise RuntimeError( 'Without DBus support the --embed-* options are not available' ) if len(embed_options_set) > 0 and len(embed_options_set) < len( embed_options): raise RuntimeError( 'Missing option(s) - all \'--embed-*\' options must be set' ) if len(embed_options_set) > 0 and self._options.clear_config: raise RuntimeError( 'Option --clear-config can only be used without any --embed-* option' ) groups = (list_options_set, command_options_set, embed_options_set) groups_set = [opt for opt in groups if len(opt) > 0] if len(groups_set) > 1: raise RuntimeError( 'Options from different groups (--list, --command, --embed) can not be used together' ) except RuntimeError as e: print(str(e)) #parser.parse_args(['--help']) # calling --help will exit return 1 # set implicit option dependencies if self._options.standalone_plugin is not None: self._options.lock_perspective = True # use qt/glib mainloop integration to get dbus mainloop working if self._dbus_available: from dbus.mainloop.glib import DBusGMainLoop from dbus import DBusException, Interface, SessionBus DBusGMainLoop(set_as_default=True) # create application context containing various relevant information from .application_context import ApplicationContext context = ApplicationContext() context.options = self._options # non-special applications provide various dbus interfaces if self._dbus_available: context.provide_app_dbus_interfaces = len(groups_set) == 0 context.dbus_base_bus_name = 'org.ros.qt_gui' if context.provide_app_dbus_interfaces: context.dbus_unique_bus_name = context.dbus_base_bus_name + '.pid%d' % os.getpid( ) # provide pid of application via dbus from .application_dbus_interface import ApplicationDBusInterface _dbus_server = ApplicationDBusInterface( context.dbus_base_bus_name) # determine host bus name, either based on pid given on command line or via dbus application interface if any other instance is available if len(command_options_set) > 0 or len(embed_options_set) > 0: host_pid = None if self._options.command_pid is not None: host_pid = self._options.command_pid else: try: remote_object = SessionBus().get_object( context.dbus_base_bus_name, '/Application') except DBusException: pass else: remote_interface = Interface( remote_object, context.dbus_base_bus_name + '.Application') host_pid = remote_interface.get_pid() if host_pid is not None: context.dbus_host_bus_name = context.dbus_base_bus_name + '.pid%d' % host_pid # execute command on host application instance if len(command_options_set) > 0: if self._options.command_start_plugin is not None: try: remote_object = SessionBus().get_object( context.dbus_host_bus_name, '/PluginManager') except DBusException: (rc, msg) = (1, 'unable to communicate with GUI instance "%s"' % context.dbus_host_bus_name) else: remote_interface = Interface( remote_object, context.dbus_base_bus_name + '.PluginManager') (rc, msg) = remote_interface.start_plugin( self._options.command_start_plugin, ' '.join(self._options.args)) if rc == 0: print('qt_gui_main() started plugin "%s" in GUI "%s"' % (msg, context.dbus_host_bus_name)) else: print( 'qt_gui_main() could not start plugin "%s" in GUI "%s": %s' % (self._options.command_start_plugin, context.dbus_host_bus_name, msg)) return rc elif self._options.command_switch_perspective is not None: remote_object = SessionBus().get_object( context.dbus_host_bus_name, '/PerspectiveManager') remote_interface = Interface( remote_object, context.dbus_base_bus_name + '.PerspectiveManager') remote_interface.switch_perspective( self._options.command_switch_perspective) print( 'qt_gui_main() switched to perspective "%s" in GUI "%s"' % (self._options.command_switch_perspective, context.dbus_host_bus_name)) return 0 raise RuntimeError('Unknown command not handled') # choose selected or default qt binding setattr(sys, 'SELECT_QT_BINDING', self._options.qt_binding) from python_qt_binding import QT_BINDING from python_qt_binding.QtCore import qDebug, qInstallMsgHandler, QSettings, Qt, QtCriticalMsg, QtDebugMsg, QtFatalMsg, QTimer, QtWarningMsg from python_qt_binding.QtGui import QAction, QApplication, QIcon, QMenuBar from .about_handler import AboutHandler from .composite_plugin_provider import CompositePluginProvider from .help_provider import HelpProvider from .main_window import MainWindow from .perspective_manager import PerspectiveManager from .plugin_manager import PluginManager def message_handler(type_, msg): colored_output = 'TERM' in os.environ and 'ANSI_COLORS_DISABLED' not in os.environ cyan_color = '\033[36m' if colored_output else '' red_color = '\033[31m' if colored_output else '' reset_color = '\033[0m' if colored_output else '' if type_ == QtDebugMsg and self._options.verbose: print(msg, file=sys.stderr) elif type_ == QtWarningMsg: print(cyan_color + msg + reset_color, file=sys.stderr) elif type_ == QtCriticalMsg: print(red_color + msg + reset_color, file=sys.stderr) elif type_ == QtFatalMsg: print(red_color + msg + reset_color, file=sys.stderr) sys.exit(1) qInstallMsgHandler(message_handler) app = QApplication(argv) app.setAttribute(Qt.AA_DontShowIconsInMenus, False) self.__check_icon_theme_compliance() if len(embed_options_set) == 0: settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'ros.org', self._settings_filename) if self._options.clear_config: settings.clear() main_window = MainWindow() main_window.setDockNestingEnabled(True) main_window.statusBar() def sigint_handler(*args): qDebug('\nsigint_handler()') main_window.close() signal.signal(signal.SIGINT, sigint_handler) # the timer enables triggering the sigint_handler timer = QTimer() timer.start(500) timer.timeout.connect(lambda: None) # create own menu bar to share one menu bar on Mac menu_bar = QMenuBar() menu_bar.setNativeMenuBar(False) if not self._options.lock_perspective: main_window.setMenuBar(menu_bar) file_menu = menu_bar.addMenu(menu_bar.tr('File')) action = QAction(file_menu.tr('Quit'), file_menu) action.setIcon(QIcon.fromTheme('application-exit')) action.triggered.connect(main_window.close) file_menu.addAction(action) else: app.setQuitOnLastWindowClosed(False) settings = None main_window = None menu_bar = None self._add_plugin_providers() # setup plugin manager plugin_provider = CompositePluginProvider(self.plugin_providers) plugin_manager = PluginManager(plugin_provider, context) if self._options.list_plugins: # output available plugins print('\n'.join(sorted(plugin_manager.get_plugins().values()))) return 0 help_provider = HelpProvider() plugin_manager.plugin_help_signal.connect( help_provider.plugin_help_request) # setup perspective manager if settings is not None: perspective_manager = PerspectiveManager(settings, context) if self._options.list_perspectives: # output available perspectives print('\n'.join(sorted(perspective_manager.perspectives))) return 0 else: perspective_manager = None if main_window is not None: plugin_manager.set_main_window(main_window, menu_bar) if settings is not None and menu_bar is not None: perspective_menu = menu_bar.addMenu(menu_bar.tr('Perspectives')) perspective_manager.set_menu(perspective_menu) # connect various signals and slots if perspective_manager is not None and main_window is not None: # signal changed perspective to update window title perspective_manager.perspective_changed_signal.connect( main_window.perspective_changed) # signal new settings due to changed perspective perspective_manager.save_settings_signal.connect( main_window.save_settings) perspective_manager.restore_settings_signal.connect( main_window.restore_settings) perspective_manager.restore_settings_without_plugin_changes_signal.connect( main_window.restore_settings) if perspective_manager is not None and plugin_manager is not None: perspective_manager.save_settings_signal.connect( plugin_manager.save_settings) plugin_manager.save_settings_completed_signal.connect( perspective_manager.save_settings_completed) perspective_manager.restore_settings_signal.connect( plugin_manager.restore_settings) perspective_manager.restore_settings_without_plugin_changes_signal.connect( plugin_manager.restore_settings_without_plugins) if plugin_manager is not None and main_window is not None: # signal before changing plugins to save window state plugin_manager.plugins_about_to_change_signal.connect( main_window.save_setup) # signal changed plugins to restore window state plugin_manager.plugins_changed_signal.connect( main_window.restore_state) # signal save settings to store plugin setup on close main_window.save_settings_before_close_signal.connect( plugin_manager.close_application) # signal save and shutdown called for all plugins, trigger closing main window again plugin_manager.close_application_signal.connect( main_window.close, type=Qt.QueuedConnection) if main_window is not None and menu_bar is not None: about_handler = AboutHandler(main_window) help_menu = menu_bar.addMenu(menu_bar.tr('Help')) action = QAction(file_menu.tr('About'), help_menu) action.setIcon(QIcon.fromTheme('help-about')) action.triggered.connect(about_handler.show) help_menu.addAction(action) # set initial size - only used without saved configuration if main_window is not None: main_window.resize(600, 450) main_window.move(100, 100) # ensure that qt_gui/src is in sys.path src_path = os.path.realpath( os.path.join(os.path.dirname(__file__), '..')) if src_path not in sys.path: sys.path.append(src_path) # load specific plugin plugin = None plugin_serial = None if self._options.embed_plugin is not None: plugin = self._options.embed_plugin plugin_serial = self._options.embed_plugin_serial elif self._options.standalone_plugin is not None: plugin = self._options.standalone_plugin plugin_serial = 0 if plugin is not None: plugins = plugin_manager.find_plugins_by_name(plugin) if len(plugins) == 0: print('qt_gui_main() found no plugin matching "%s"' % plugin) return 1 elif len(plugins) > 1: print( 'qt_gui_main() found multiple plugins matching "%s"\n%s' % (plugin, '\n'.join(plugins.values()))) return 1 plugin = plugins.keys()[0] qDebug('QtBindingHelper using %s' % QT_BINDING) plugin_manager.discover() self._caching_hook() if self._options.reload_import: qDebug( 'ReloadImporter() automatically reload all subsequent imports') from .reload_importer import ReloadImporter _reload_importer = ReloadImporter() self._add_reload_paths(_reload_importer) _reload_importer.enable() # switch perspective if perspective_manager is not None: if not plugin: perspective_manager.set_perspective(self._options.perspective) else: perspective_manager.set_perspective( plugin, hide_and_without_plugin_changes=True) # load specific plugin if plugin: plugin_manager.load_plugin(plugin, plugin_serial, self._options.args) if main_window is not None: main_window.show() return app.exec_()
def __init__(self, proxymodel, minimal=False): """ :param proxymodel: the proxy model to display in the widget,''QSortFilterProxyModel'' :param minimal: if true the load, save and column buttons will be hidden as well as the filter splitter, ''bool'' """ super(ConsoleWidget, self).__init__() ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'console_widget.ui') loadUi(ui_file, self, {'ConsoleTableView': ConsoleTableView}) if minimal: self.load_button.hide() self.save_button.hide() self.column_resize_button.hide() self.setObjectName('ConsoleWidget') self.table_view.setModel(proxymodel) self._proxymodel = proxymodel self._datamodel = proxymodel.sourceModel() self._columnwidth = (600, 140, 200, 430, 200, 600) for idx, width in enumerate(self._columnwidth): self.table_view.horizontalHeader().resizeSection(idx, width) self.table_view.sortByColumn(3, Qt.DescendingOrder) self.add_exclude_button.setIcon(QIcon.fromTheme('list-add')) self.add_highlight_button.setIcon(QIcon.fromTheme('list-add')) self._pauseicon = QIcon.fromTheme('media-playback-pause') self._recordicon = QIcon.fromTheme('media-record') self.pause_button.setIcon(self._pauseicon) self.load_button.setIcon(QIcon.fromTheme('document-open')) self.save_button.setIcon(QIcon.fromTheme('document-save')) self.highlight_exclude_button.setIcon( QIcon.fromTheme('format-text-strikethrough')) self.pause_button.clicked[bool].connect(self._handle_pause_clicked) self.load_button.clicked[bool].connect(self._handle_load_clicked) self.save_button.clicked[bool].connect(self._handle_save_clicked) self.column_resize_button.clicked[bool].connect( self._handle_column_resize_clicked) self.clear_button.clicked[bool].connect( self._handle_clear_button_clicked) self.table_view.mouseDoubleClickEvent = self._handle_mouse_double_click self.table_view.mousePressEvent = self._handle_mouse_press self.table_view.keyPressEvent = self._handle_custom_keypress self.severitylist = self._datamodel.get_severity_list() # These are lists of Tuples = (,) self._exclude_filters = [] self._highlight_filters = [] self.highlight_exclude_button.clicked[bool].connect( self._proxymodel.set_show_highlighted_only) self.add_highlight_button.clicked.connect(self._add_highlight_filter) self.add_exclude_button.clicked.connect(self._add_exclude_filter) # Filter factory dictionary: # index 0 is a label describing the widget, index 1 is the class that provides filtering logic # index 2 is the widget that sets the data in the filter class, index 3 are the arguments for the widget class constructor self.filter_factory = { 'message': (self.tr('Message Filter'), MessageFilter, TextFilterWidget, []), 'severity': (self.tr('Severity Filter'), SeverityFilter, ListFilterWidget, [self._datamodel.get_severity_list]), 'node': (self.tr('Node Filter'), NodeFilter, ListFilterWidget, [self._datamodel.get_unique_col_data, 2]), 'time': (self.tr('Time Filter'), TimeFilter, TimeFilterWidget, [self.get_time_range_from_selection]), 'topic': (self.tr('Topic Filter'), TopicFilter, ListFilterWidget, [self._datamodel.get_unique_col_data, 4]), 'location': (self.tr('Location Filter'), LocationFilter, TextFilterWidget, []), 'custom': (self.tr('Custom Filter'), CustomFilter, CustomFilterWidget, [ self._datamodel.get_severity_list, self._datamodel.get_unique_col_data, 2, self._datamodel.get_unique_col_data, 4 ]) } # list of TextBrowserDialogs to close when cleaning up self._browsers = [] # This defaults the filters panel to start by taking 50% of the available space if (minimal): self.table_splitter.setSizes([1, 0]) else: self.table_splitter.setSizes([1, 1]) self.exclude_table.resizeColumnsToContents() self.highlight_table.resizeColumnsToContents()
def _on_partial_publishing(self): self.updateIconView(QIcon(':/icons/state_part.png'))
def __init__(self): super(BTWidget, self).__init__() self.setObjectName('BTWidget') self._graph = None self._current_dotcode = None self._initialized = False # dot_to_qt transforms into Qt elements using dot layout self.dot_to_qt = DotToQtGenerator() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_bt'), 'resource', 'rqt_bt.ui') loadUi(ui_file, self, {'InteractiveGraphicsView': InteractiveGraphicsView}) self.refresh_timer = QTimer(self) self.refresh_timer.start(self._redraw_interval) self.refresh_timer.timeout.connect(self._refresh_rosgraph) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self.graphics_view.setScene(self._scene) self.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh')) self.refresh_graph_push_button.clicked.connect(self._update_rosgraph) self.highlight_connections_check_box.toggled.connect( self._redraw_graph_view) self.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view) self.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original')) self.fit_in_view_push_button.clicked.connect(self._fit_in_view) self.depth_spin_box.setMinimum(-1) self.depth_spin_box.valueChanged.connect(self._refresh_rosgraph) self.save_dot_push_button.setIcon(QIcon.fromTheme('document-save-as')) self.save_dot_push_button.clicked.connect(self._save_dot) self.save_as_svg_push_button.setIcon( QIcon.fromTheme('document-save-as')) self.save_as_svg_push_button.clicked.connect(self._save_svg) self.save_as_image_push_button.setIcon(QIcon.fromTheme('image')) self.save_as_image_push_button.clicked.connect(self._save_image) self.run_push_button.setIcon(QIcon.fromTheme('media-playback-pause')) self.run_push_button.clicked.connect(self._run_bt) self._update_rosgraph() self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() # generator builds tree graph bt_sub_name = '/cyborg/bt/behavior_tree' bt_update_sub_name = '/cyborg/bt/behavior_tree_updates' bt_enabled_sub_name = '/cyborg/bt/enabled' bt_enable_srv_name = '/cyborg/bt/enable' self._bt_enabled = True rospy.Subscriber(bt_enabled_sub_name, Bool, self._bt_enabled_cb) self._bt_enable_srv = rospy.ServiceProxy(bt_enable_srv_name, SetBool) bt_data = BTData(bt_sub_name, bt_update_sub_name) self.dotcode_generator = RosBTDotcodeGenerator(bt_data)
def __init__(self, context): super(RosPackGraph, self).__init__(context) self.initialized = False self._current_dotcode = None self._update_thread = WorkerThread(self._update_thread_run, self._update_finished) self._nodes = {} self._edges = {} self._options = {} self._options_serialized = '' self.setObjectName('RosPackGraph') rospack = rospkg.RosPack() rosstack = rospkg.RosStack() # factory builds generic dotcode items self.dotcode_factory = PydotFactory() # self.dotcode_factory = PygraphvizFactory() # generator builds rosgraph self.dotcode_generator = RosPackageGraphDotcodeGenerator( rospack, rosstack) # dot_to_qt transforms into Qt elements using dot layout self.dot_to_qt = DotToQtGenerator() self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_dep'), 'resource', 'RosPackGraph.ui') loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self._widget.setObjectName('RosPackGraphUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) self._widget.depth_combo_box.insertItem(0, self.tr('infinite'), -1) self._widget.depth_combo_box.insertItem(1, self.tr('1'), 2) self._widget.depth_combo_box.insertItem(2, self.tr('2'), 3) self._widget.depth_combo_box.insertItem(3, self.tr('3'), 4) self._widget.depth_combo_box.insertItem(4, self.tr('4'), 5) self._widget.depth_combo_box.currentIndexChanged.connect( self._refresh_rospackgraph) self._widget.directions_combo_box.insertItem(0, self.tr('depends'), 0) self._widget.directions_combo_box.insertItem(1, self.tr('depends_on'), 1) self._widget.directions_combo_box.insertItem(2, self.tr('both'), 2) self._widget.directions_combo_box.currentIndexChanged.connect( self._refresh_rospackgraph) self._widget.package_type_combo_box.insertItem(0, self.tr('wet & dry'), 3) self._widget.package_type_combo_box.insertItem(1, self.tr('wet only'), 2) self._widget.package_type_combo_box.insertItem(2, self.tr('dry only'), 1) self._widget.package_type_combo_box.currentIndexChanged.connect( self._refresh_rospackgraph) completionmodel = StackageCompletionModel( self._widget.filter_line_edit, rospack, rosstack) completer = RepeatedWordCompleter(completionmodel, self) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setWrapAround(True) completer.setCaseSensitivity(Qt.CaseInsensitive) self._widget.filter_line_edit.editingFinished.connect( self._refresh_rospackgraph) self._widget.filter_line_edit.setCompleter(completer) self._widget.filter_line_edit.selectionChanged.connect( self._clear_filter) self._widget.with_stacks_check_box.clicked.connect( self._refresh_rospackgraph) self._widget.mark_check_box.clicked.connect(self._refresh_rospackgraph) self._widget.colorize_check_box.clicked.connect( self._refresh_rospackgraph) self._widget.hide_transitives_check_box.clicked.connect( self._refresh_rospackgraph) self._widget.refresh_graph_push_button.setIcon( QIcon.fromTheme('view-refresh')) self._widget.refresh_graph_push_button.pressed.connect( self._update_rospackgraph) self._widget.highlight_connections_check_box.toggled.connect( self._refresh_rospackgraph) self._widget.auto_fit_graph_check_box.toggled.connect( self._refresh_rospackgraph) self._widget.fit_in_view_push_button.setIcon( QIcon.fromTheme('zoom-original')) self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view) self._widget.load_dot_push_button.setIcon( QIcon.fromTheme('document-open')) self._widget.load_dot_push_button.pressed.connect(self._load_dot) self._widget.save_dot_push_button.setIcon( QIcon.fromTheme('document-save-as')) self._widget.save_dot_push_button.pressed.connect(self._save_dot) self._widget.save_as_svg_push_button.setIcon( QIcon.fromTheme('document-save-as')) self._widget.save_as_svg_push_button.pressed.connect(self._save_svg) self._widget.save_as_image_push_button.setIcon( QIcon.fromTheme('image')) self._widget.save_as_image_push_button.pressed.connect( self._save_image) self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() context.add_widget(self._widget) # If in either of following case, this turnes True # - 1st filtering key is already input by user # - filtering key is restored self._filtering_started = False
def _on_publishing(self): self.updateIconView(QIcon(':/icons/state_run.png'))
def __init__(self, context): """ :param context: plugin context hook to enable adding widgets as a ROS_GUI pane, ''PluginContext'' """ super(BagWidget, self).__init__() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_bag'), 'resource', 'bag_widget.ui') loadUi(ui_file, self, {'BagGraphicsView': BagGraphicsView}) self.setObjectName('BagWidget') self._timeline = BagTimeline(context) self.graphics_view.setScene(self._timeline) self.graphics_view.resizeEvent = self._resizeEvent self.graphics_view.setMouseTracking(True) self.play_icon = QIcon.fromTheme('media-playback-start') self.pause_icon = QIcon.fromTheme('media-playback-pause') self.play_button.setIcon(self.play_icon) self.begin_button.setIcon(QIcon.fromTheme('media-skip-backward')) self.end_button.setIcon(QIcon.fromTheme('media-skip-forward')) self.slower_button.setIcon(QIcon.fromTheme('media-seek-backward')) self.faster_button.setIcon(QIcon.fromTheme('media-seek-forward')) self.zoom_in_button.setIcon(QIcon.fromTheme('zoom-in')) self.zoom_out_button.setIcon(QIcon.fromTheme('zoom-out')) self.zoom_all_button.setIcon(QIcon.fromTheme('zoom-original')) self.thumbs_button.setIcon(QIcon.fromTheme('insert-image')) self.record_button.setIcon(QIcon.fromTheme('media-record')) self.load_button.setIcon(QIcon.fromTheme('document-open')) self.save_button.setIcon(QIcon.fromTheme('document-save')) self.play_button.clicked[bool].connect(self._handle_play_clicked) self.thumbs_button.clicked[bool].connect(self._handle_thumbs_clicked) self.zoom_in_button.clicked[bool].connect(self._handle_zoom_in_clicked) self.zoom_out_button.clicked[bool].connect( self._handle_zoom_out_clicked) self.zoom_all_button.clicked[bool].connect( self._handle_zoom_all_clicked) self.faster_button.clicked[bool].connect(self._handle_faster_clicked) self.slower_button.clicked[bool].connect(self._handle_slower_clicked) self.begin_button.clicked[bool].connect(self._handle_begin_clicked) self.end_button.clicked[bool].connect(self._handle_end_clicked) self.record_button.clicked[bool].connect(self._handle_record_clicked) self.load_button.clicked[bool].connect(self._handle_load_clicked) self.save_button.clicked[bool].connect(self._handle_save_clicked) self.graphics_view.mousePressEvent = self._timeline.on_mouse_down self.graphics_view.mouseReleaseEvent = self._timeline.on_mouse_up self.graphics_view.mouseMoveEvent = self._timeline.on_mouse_move self.graphics_view.wheelEvent = self._timeline.on_mousewheel self.closeEvent = self.handle_close self.keyPressEvent = self.on_key_press # TODO when the closeEvent is properly called by ROS_GUI implement that event instead of destroyed self.destroyed.connect(self.handle_destroy) self.graphics_view.keyPressEvent = self.graphics_view_on_key_press self.play_button.setEnabled(False) self.thumbs_button.setEnabled(False) self.zoom_in_button.setEnabled(False) self.zoom_out_button.setEnabled(False) self.zoom_all_button.setEnabled(False) self.faster_button.setEnabled(False) self.slower_button.setEnabled(False) self.begin_button.setEnabled(False) self.end_button.setEnabled(False) self.save_button.setEnabled(False) self._recording = False self._timeline.status_bar_changed_signal.connect( self._update_status_bar)
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 main(self, argv=None, standalone=None, plugin_argument_provider=None, plugin_manager_settings_prefix=''): if argv is None: argv = sys.argv # extract --args and everything behind manually since argparse can not handle that arguments = argv[1:] # extract plugin specific args when not being invoked in standalone mode programmatically if not standalone: plugin_args = [] if '--args' in arguments: index = arguments.index('--args') plugin_args = arguments[index + 1:] arguments = arguments[0:index + 1] parser = ArgumentParser(os.path.basename(Main.main_filename), add_help=False) self.add_arguments(parser, standalone=bool(standalone), plugin_argument_provider=plugin_argument_provider) self._options = parser.parse_args(arguments) if standalone: # rerun parsing to separate common arguments from plugin specific arguments parser = ArgumentParser(os.path.basename(Main.main_filename), add_help=False) self.add_arguments(parser, standalone=bool(standalone)) self._options, plugin_args = parser.parse_known_args(arguments) self._options.plugin_args = plugin_args # set default values for options not available in standalone mode if standalone: self._options.freeze_layout = False self._options.lock_perspective = False self._options.multi_process = False self._options.perspective = None self._options.perspective_file = None self._options.standalone_plugin = standalone self._options.list_perspectives = False self._options.list_plugins = False self._options.command_pid = None self._options.command_start_plugin = None self._options.command_switch_perspective = None self._options.embed_plugin = None self._options.embed_plugin_serial = None self._options.embed_plugin_address = None # check option dependencies try: if self._options.plugin_args and not self._options.standalone_plugin and not self._options.command_start_plugin and not self._options.embed_plugin: raise RuntimeError( 'Option --args can only be used together with either --standalone, --command-start-plugin or --embed-plugin option' ) if self._options.freeze_layout and not self._options.lock_perspective: raise RuntimeError( 'Option --freeze_layout can only be used together with the --lock_perspective option' ) list_options = (self._options.list_perspectives, self._options.list_plugins) list_options_set = [ opt for opt in list_options if opt is not False ] if len(list_options_set) > 1: raise RuntimeError( 'Only one --list-* option can be used at a time') command_options = (self._options.command_start_plugin, self._options.command_switch_perspective) command_options_set = [ opt for opt in command_options if opt is not None ] if len(command_options_set) > 0 and not self._dbus_available: raise RuntimeError( 'Without DBus support the --command-* options are not available' ) if len(command_options_set) > 1: raise RuntimeError( 'Only one --command-* option can be used at a time (except --command-pid which is optional)' ) if len(command_options_set ) == 0 and self._options.command_pid is not None: raise RuntimeError( 'Option --command_pid can only be used together with an other --command-* option' ) embed_options = (self._options.embed_plugin, self._options.embed_plugin_serial, self._options.embed_plugin_address) embed_options_set = [ opt for opt in embed_options if opt is not None ] if len(command_options_set) > 0 and not self._dbus_available: raise RuntimeError( 'Without DBus support the --embed-* options are not available' ) if len(embed_options_set) > 0 and len(embed_options_set) < len( embed_options): raise RuntimeError( 'Missing option(s) - all \'--embed-*\' options must be set' ) if len(embed_options_set) > 0 and self._options.clear_config: raise RuntimeError( 'Option --clear-config can only be used without any --embed-* option' ) groups = (list_options_set, command_options_set, embed_options_set) groups_set = [opt for opt in groups if len(opt) > 0] if len(groups_set) > 1: raise RuntimeError( 'Options from different groups (--list, --command, --embed) can not be used together' ) perspective_options = (self._options.perspective, self._options.perspective_file) perspective_options_set = [ opt for opt in perspective_options if opt is not None ] if len(perspective_options_set) > 1: raise RuntimeError( 'Only one --perspective-* option can be used at a time') if self._options.perspective_file is not None and not os.path.isfile( self._options.perspective_file): raise RuntimeError( 'Option --perspective-file must reference existing file') except RuntimeError as e: print(str(e)) #parser.parse_args(['--help']) # calling --help will exit return 1 # set implicit option dependencies if self._options.standalone_plugin is not None: self._options.lock_perspective = True # create application context containing various relevant information from .application_context import ApplicationContext context = ApplicationContext() context.qtgui_path = self._qtgui_path context.options = self._options if self._dbus_available: from dbus import DBusException, Interface, SessionBus # non-special applications provide various dbus interfaces if self._dbus_available: context.provide_app_dbus_interfaces = len(groups_set) == 0 context.dbus_base_bus_name = 'org.ros.qt_gui' if context.provide_app_dbus_interfaces: context.dbus_unique_bus_name = context.dbus_base_bus_name + '.pid%d' % os.getpid( ) # provide pid of application via dbus from .application_dbus_interface import ApplicationDBusInterface _dbus_server = ApplicationDBusInterface( context.dbus_base_bus_name) # determine host bus name, either based on pid given on command line or via dbus application interface if any other instance is available if len(command_options_set) > 0 or len(embed_options_set) > 0: host_pid = None if self._options.command_pid is not None: host_pid = self._options.command_pid else: try: remote_object = SessionBus().get_object( context.dbus_base_bus_name, '/Application') except DBusException: pass else: remote_interface = Interface( remote_object, context.dbus_base_bus_name + '.Application') host_pid = remote_interface.get_pid() if host_pid is not None: context.dbus_host_bus_name = context.dbus_base_bus_name + '.pid%d' % host_pid # execute command on host application instance if len(command_options_set) > 0: if self._options.command_start_plugin is not None: try: remote_object = SessionBus().get_object( context.dbus_host_bus_name, '/PluginManager') except DBusException: (rc, msg) = (1, 'unable to communicate with GUI instance "%s"' % context.dbus_host_bus_name) else: remote_interface = Interface( remote_object, context.dbus_base_bus_name + '.PluginManager') (rc, msg) = remote_interface.start_plugin( self._options.command_start_plugin, ' '.join(self._options.plugin_args)) if rc == 0: print('qt_gui_main() started plugin "%s" in GUI "%s"' % (msg, context.dbus_host_bus_name)) else: print( 'qt_gui_main() could not start plugin "%s" in GUI "%s": %s' % (self._options.command_start_plugin, context.dbus_host_bus_name, msg)) return rc elif self._options.command_switch_perspective is not None: remote_object = SessionBus().get_object( context.dbus_host_bus_name, '/PerspectiveManager') remote_interface = Interface( remote_object, context.dbus_base_bus_name + '.PerspectiveManager') remote_interface.switch_perspective( self._options.command_switch_perspective) print( 'qt_gui_main() switched to perspective "%s" in GUI "%s"' % (self._options.command_switch_perspective, context.dbus_host_bus_name)) return 0 raise RuntimeError('Unknown command not handled') # choose selected or default qt binding setattr(sys, 'SELECT_QT_BINDING', self._options.qt_binding) from python_qt_binding import QT_BINDING from python_qt_binding.QtCore import qDebug, qInstallMessageHandler, QSettings, Qt, QtCriticalMsg, QtDebugMsg, QtFatalMsg, QTimer, QtWarningMsg from python_qt_binding.QtGui import QIcon from python_qt_binding.QtWidgets import QAction, QMenuBar from .about_handler import AboutHandler from .composite_plugin_provider import CompositePluginProvider from .container_manager import ContainerManager from .help_provider import HelpProvider from .icon_loader import get_icon from .main_window import MainWindow from .minimized_dock_widgets_toolbar import MinimizedDockWidgetsToolbar from .perspective_manager import PerspectiveManager from .plugin_manager import PluginManager # TODO PySide2 segfaults when invoking this custom message handler atm if QT_BINDING != 'pyside': def message_handler(type_, context, msg): colored_output = 'TERM' in os.environ and 'ANSI_COLORS_DISABLED' not in os.environ cyan_color = '\033[36m' if colored_output else '' red_color = '\033[31m' if colored_output else '' reset_color = '\033[0m' if colored_output else '' if type_ == QtDebugMsg and self._options.verbose: print(msg, file=sys.stderr) elif type_ == QtWarningMsg: print(cyan_color + msg + reset_color, file=sys.stderr) elif type_ == QtCriticalMsg: print(red_color + msg + reset_color, file=sys.stderr) elif type_ == QtFatalMsg: print(red_color + msg + reset_color, file=sys.stderr) sys.exit(1) qInstallMessageHandler(message_handler) app = self.create_application(argv) self._check_icon_theme_compliance() settings = QSettings(QSettings.IniFormat, QSettings.UserScope, 'ros.org', self._settings_filename) if len(embed_options_set) == 0: if self._options.clear_config: settings.clear() main_window = MainWindow() if self._options.on_top: main_window.setWindowFlags(Qt.WindowStaysOnTopHint) main_window.statusBar() def sigint_handler(*args): qDebug('\nsigint_handler()') main_window.close() signal.signal(signal.SIGINT, sigint_handler) # the timer enables triggering the sigint_handler timer = QTimer() timer.start(500) timer.timeout.connect(lambda: None) menu_bar = main_window.menuBar() file_menu = menu_bar.addMenu(menu_bar.tr('&File')) action = QAction(file_menu.tr('&Quit'), file_menu) action.setIcon(QIcon.fromTheme('application-exit')) action.triggered.connect(main_window.close) file_menu.addAction(action) else: app.setQuitOnLastWindowClosed(False) main_window = None menu_bar = None self._add_plugin_providers() # setup plugin manager plugin_provider = CompositePluginProvider(self.plugin_providers) plugin_manager = PluginManager( plugin_provider, settings, context, settings_prefix=plugin_manager_settings_prefix) if self._options.list_plugins: # output available plugins print('\n'.join(sorted(plugin_manager.get_plugins().values()))) return 0 help_provider = HelpProvider() plugin_manager.plugin_help_signal.connect( help_provider.plugin_help_request) # setup perspective manager if main_window is not None: perspective_manager = PerspectiveManager(settings, context) if self._options.list_perspectives: # output available perspectives print('\n'.join(sorted(perspective_manager.perspectives))) return 0 else: perspective_manager = None if main_window is not None: container_manager = ContainerManager(main_window, plugin_manager) plugin_manager.set_main_window( main_window, menu_bar if not self._options.lock_perspective else None, container_manager) if not self._options.freeze_layout: minimized_dock_widgets_toolbar = MinimizedDockWidgetsToolbar( container_manager, main_window) main_window.addToolBar(Qt.BottomToolBarArea, minimized_dock_widgets_toolbar) plugin_manager.set_minimized_dock_widgets_toolbar( minimized_dock_widgets_toolbar) if menu_bar is not None and not self._options.lock_perspective: perspective_menu = menu_bar.addMenu(menu_bar.tr('P&erspectives')) perspective_manager.set_menu(perspective_menu) # connect various signals and slots if perspective_manager is not None and main_window is not None: # signal changed perspective to update window title perspective_manager.perspective_changed_signal.connect( main_window.perspective_changed) # signal new settings due to changed perspective perspective_manager.save_settings_signal.connect( main_window.save_settings) perspective_manager.restore_settings_signal.connect( main_window.restore_settings) perspective_manager.restore_settings_without_plugin_changes_signal.connect( main_window.restore_settings) if perspective_manager is not None and plugin_manager is not None: perspective_manager.save_settings_signal.connect( plugin_manager.save_settings) plugin_manager.save_settings_completed_signal.connect( perspective_manager.save_settings_completed) perspective_manager.restore_settings_signal.connect( plugin_manager.restore_settings) perspective_manager.restore_settings_without_plugin_changes_signal.connect( plugin_manager.restore_settings_without_plugins) if plugin_manager is not None and main_window is not None: # signal before changing plugins to save window state plugin_manager.plugins_about_to_change_signal.connect( main_window.save_setup) # signal changed plugins to restore window state plugin_manager.plugins_changed_signal.connect( main_window.restore_state) # signal save settings to store plugin setup on close main_window.save_settings_before_close_signal.connect( plugin_manager.close_application) # signal save and shutdown called for all plugins, trigger closing main window again plugin_manager.close_application_signal.connect( main_window.close, type=Qt.QueuedConnection) if main_window is not None and menu_bar is not None: about_handler = AboutHandler(context.qtgui_path, main_window) help_menu = menu_bar.addMenu(menu_bar.tr('&Help')) action = QAction(file_menu.tr('&About'), help_menu) action.setIcon(QIcon.fromTheme('help-about')) action.triggered.connect(about_handler.show) help_menu.addAction(action) # set initial size - only used without saved configuration if main_window is not None: main_window.resize(600, 450) main_window.move(100, 100) # ensure that qt_gui/src is in sys.path src_path = os.path.realpath( os.path.join(os.path.dirname(__file__), '..')) if src_path not in sys.path: sys.path.append(src_path) # load specific plugin plugin = None plugin_serial = None if self._options.embed_plugin is not None: plugin = self._options.embed_plugin plugin_serial = self._options.embed_plugin_serial elif self._options.standalone_plugin is not None: plugin = self._options.standalone_plugin plugin_serial = 0 if plugin is not None: plugins = plugin_manager.find_plugins_by_name(plugin) if len(plugins) == 0: print('qt_gui_main() found no plugin matching "%s"' % plugin) return 1 elif len(plugins) > 1: print( 'qt_gui_main() found multiple plugins matching "%s"\n%s' % (plugin, '\n'.join(plugins.values()))) return 1 plugin = plugins.keys()[0] qDebug('QtBindingHelper using %s' % QT_BINDING) plugin_manager.discover() if self._options.reload_import: qDebug( 'ReloadImporter() automatically reload all subsequent imports') from .reload_importer import ReloadImporter _reload_importer = ReloadImporter() self._add_reload_paths(_reload_importer) _reload_importer.enable() # switch perspective if perspective_manager is not None: if plugin: perspective_manager.set_perspective( plugin, hide_and_without_plugin_changes=True) elif self._options.perspective_file: perspective_manager.import_perspective_from_file( self._options.perspective_file, perspective_manager.HIDDEN_PREFIX + os.path.basename(self._options.perspective_file)) else: perspective_manager.set_perspective(self._options.perspective) # load specific plugin if plugin: plugin_manager.load_plugin(plugin, plugin_serial, self._options.plugin_args) running = plugin_manager.is_plugin_running(plugin, plugin_serial) if not running: return 1 if self._options.standalone_plugin: # use icon of standalone plugin (if available) for application plugin_descriptor = plugin_manager.get_plugin_descriptor( plugin) action_attributes = plugin_descriptor.action_attributes() if 'icon' in action_attributes and action_attributes[ 'icon'] is not None: base_path = plugin_descriptor.attributes().get( 'plugin_path') try: icon = get_icon( action_attributes['icon'], action_attributes.get('icontype', None), base_path) except UserWarning: pass else: app.setWindowIcon(icon) if main_window is not None: main_window.show() if sys.platform == 'darwin': main_window.raise_() return app.exec_()
def __init__(self, context): super(GatewayGraph, self).__init__(context) self.initialised = False self.setObjectName('Gateway Graph') self._current_dotcode = None self._widget = QWidget() # factory builds generic dotcode items self.dotcode_factory = PydotFactory() # self.dotcode_factory = PygraphvizFactory() self.dotcode_generator = RosGraphDotcodeGenerator() self.dot_to_qt = DotToQtGenerator() self._graph = Graph() rospack = rospkg.RosPack() ui_file = os.path.join(rospack.get_path('rocon_gateway_graph'), 'ui', 'gateway_graph.ui') #ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ui', 'gateway_graph.ui') loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self._widget.setObjectName('GatewayGraphUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) self._widget.refresh_graph_push_button.setIcon( QIcon.fromTheme('view-refresh')) self._widget.refresh_graph_push_button.pressed.connect( self._update_gateway_graph) self._widget.graph_type_combo_box.insertItem(0, self.tr('Gateways'), GATEWAY_GATEWAY_GRAPH) self._widget.graph_type_combo_box.insertItem( 1, self.tr('Pulled Connections'), GATEWAY_PULLED_GRAPH) self._widget.graph_type_combo_box.insertItem( 2, self.tr('Flipped Connections'), GATEWAY_FLIPPED_GRAPH) self._widget.graph_type_combo_box.setCurrentIndex(0) self._widget.graph_type_combo_box.currentIndexChanged.connect( self._refresh_rosgraph) self.node_completionmodel = NamespaceCompletionModel( self._widget.filter_line_edit, False) completer = RepeatedWordCompleter(self.node_completionmodel, self) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setWrapAround(True) completer.setCaseSensitivity(Qt.CaseInsensitive) self._widget.filter_line_edit.editingFinished.connect( self._refresh_rosgraph) self._widget.filter_line_edit.setCompleter(completer) self.topic_completionmodel = NamespaceCompletionModel( self._widget.topic_filter_line_edit, False) topic_completer = RepeatedWordCompleter(self.topic_completionmodel, self) topic_completer.setCompletionMode(QCompleter.PopupCompletion) topic_completer.setWrapAround(True) topic_completer.setCaseSensitivity(Qt.CaseInsensitive) self._widget.topic_filter_line_edit.editingFinished.connect( self._refresh_rosgraph) self._widget.topic_filter_line_edit.setCompleter(topic_completer) self._widget.namespace_cluster_check_box.clicked.connect( self._refresh_rosgraph) self._widget.watchlist_check_box.clicked.connect( self._refresh_rosgraph) self._widget.all_advertisements_check_box.clicked.connect( self._refresh_rosgraph) self._widget.highlight_connections_check_box.toggled.connect( self._redraw_graph_view) self._widget.auto_fit_graph_check_box.toggled.connect( self._redraw_graph_view) self._widget.fit_in_view_push_button.setIcon( QIcon.fromTheme('zoom-original')) self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view) self._widget.load_dot_push_button.setIcon( QIcon.fromTheme('document-open')) self._widget.load_dot_push_button.pressed.connect(self._load_dot) self._widget.save_dot_push_button.setIcon( QIcon.fromTheme('document-save-as')) self._widget.save_dot_push_button.pressed.connect(self._save_dot) self._widget.save_as_svg_push_button.setIcon( QIcon.fromTheme('document-save-as')) self._widget.save_as_svg_push_button.pressed.connect(self._save_svg) self._widget.save_as_image_push_button.setIcon( QIcon.fromTheme('image')) self._widget.save_as_image_push_button.pressed.connect( self._save_image) self._update_gateway_graph() self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() context.add_widget(self._widget)
def __init__(self, menu_button): QMenu.__init__(self) self.button = menu_button try: rqt_icon_path = roslib.packages.find_resource('rqt_gui', 'rqt.png').pop() menu_button.setText('') menu_button.setIcon(QIcon(rqt_icon_path)) # creates a default config menu self.action_rqt_console = QAction(QIcon.fromTheme('mail-message-new'), "&Console", self, statusTip='"<p>Starts a python GUI plugin for displaying and filtering ' 'ROS log messages that is connected to the selected master.</p>"', triggered=self.on_show_console_clicked) self.addAction(self.action_rqt_console) self.action_rqt_logger_level = QAction(QIcon.fromTheme('format-indent-more'), "&Logger Level", self, statusTip='"<p>Starts a python GUI plugin for configuring the level of ' 'ROS loggers that is connected to the selected master.</p>"', triggered=self.on_show_logger_level_clicked) self.addAction(self.action_rqt_logger_level) self.action_rqt_tf_tree = QAction(QIcon.fromTheme('preferences-system-network'), "&TF Tree", self, statusTip='"<p>Starts a python GUI plugin for visualizing the TF tree' 'that is connected to the selected master.</p>"', triggered=self.on_show_tf_tree_clicked) self.addAction(self.action_rqt_tf_tree) self.action_rqt_ros_graph = QAction(nm.settings().icon('button_graph.png'), "Ros &Graph", self, statusTip='"<p>Starts a python GUI plugin for visualizing the ROS computation graph' 'that is connected to the selected master</p>"', triggered=self.on_show_ros_graph_clicked) self.addAction(self.action_rqt_ros_graph) self.action_rosbag_record = QAction(QIcon.fromTheme('media-record'), "rosbag record", self, statusTip='"<p>Starts the rosbag record with selected topics</p>"', triggered=self.on_start_rosbag_clicked) self.addAction(self.action_rosbag_record) self.action_rqt_rviz = QAction(QIcon.fromTheme('image-x-generic'), "R&Viz", self, statusTip='"<p>Starts RViz</p>"', triggered=self.on_show_rviz_clicked) self.addAction(self.action_rqt_rviz) self.addSeparator() self.action_rqt = QAction(QIcon(rqt_icon_path), "&Rqt GUI", self, statusTip='"<p>Start the rqt GUI' 'that is connected to the selected master</p>"', triggered=self.on_start_rqt_clicked) self.addAction(self.action_rqt) self.action_terminal = QAction(nm.settings().icon('crystal_clear_show_io.png'), "&Terminal", self, statusTip='"<p>Start terminal on selected host</p>"', triggered=self.on_start_terminal) self.action_terminal.setShortcut(QKeySequence("Ctrl+T")) self.addAction(self.action_terminal) menu_button.setMenu(self) except Exception as _e: import traceback print(traceback.format_exc()) menu_button.setEnabled(False) menu_button.setToolTip('rqt_gui not found! Please install rqt to use its plugins!')
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Author: Isaac Saito, Ze'ev Klapow, Austin Hendrix from python_qt_binding.QtGui import QColor, QIcon import rospy # TODO: Utils and common configs are mixed in this class. # Instantiating icons that show the device status. _ERR_ICON = QIcon.fromTheme('dialog-error') _WARN_ICON = QIcon.fromTheme('dialog-warning') _OK_ICON = QIcon.fromTheme('emblem-default') # Added following this QA thread http://goo.gl/83tVZ _STALE_ICON = QIcon.fromTheme('dialog-question') _LEVEL_TO_ICON = {0: _OK_ICON, 1: _WARN_ICON, 2: _ERR_ICON, 3: _STALE_ICON} _LEVEL_TO_COLOR = {0: QColor(85, 178, 76), # green 1: QColor(222, 213, 17), # yellow 2: QColor(178, 23, 46), # red 3: QColor(40, 23, 176) # blue } _LEVEL_TO_TEXT = { 0: "OK", 1: "WARNING", 2: "ERROR", 3: "STALE" }