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)
Exemple #6
0
    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))
Exemple #16
0
 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)
Exemple #19
0
 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)
Exemple #21
0
    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'))
Exemple #27
0
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
Exemple #31
0
    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
Exemple #32
0
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
Exemple #33
0
    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)
Exemple #34
0
 def _on_wait_for_publishing(self):
     self.updateIconView(QIcon(':/icons/state_off.png'))
Exemple #35
0
 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()
Exemple #38
0
 def _publish_finished(self):
     self._publish_thread = None
     self.setIcon(QIcon())
Exemple #39
0
 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)
Exemple #40
0
 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
Exemple #41
0
 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)
Exemple #42
0
    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)
Exemple #43
0
    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()
Exemple #47
0
 def icon(self, name):
     return QIcon(self.icon_path(name))
Exemple #48
0
    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()
Exemple #49
0
    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_()
Exemple #50
0
    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()
Exemple #51
0
 def _on_partial_publishing(self):
     self.updateIconView(QIcon(':/icons/state_part.png'))
Exemple #52
0
    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)
Exemple #53
0
    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
Exemple #54
0
 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)
Exemple #56
0
    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()
Exemple #57
0
    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_()
Exemple #58
0
    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)
Exemple #59
0
 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!')
Exemple #60
0
# 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" }