def handle_header_view_customContextMenuRequested(self, pos):

        # create context menu
        menu = QMenu(self)

        action_toggle_auto_resize = menu.addAction('Auto-Resize')
        action_toggle_auto_resize.setCheckable(True)
        auto_resize_flag = (self.header().resizeMode(0) == QHeaderView.ResizeToContents)
        action_toggle_auto_resize.setChecked(auto_resize_flag)

        action_toggle_sorting = menu.addAction('Sorting')
        action_toggle_sorting.setCheckable(True)
        action_toggle_sorting.setChecked(self.isSortingEnabled())

        # show menu
        action = menu.exec_(self.header().mapToGlobal(pos))

        # evaluate user action
        if action is action_toggle_auto_resize:
            if auto_resize_flag:
                self.header().setResizeMode(QHeaderView.Interactive)
            else:
                self.header().setResizeMode(QHeaderView.ResizeToContents)

        elif action is action_toggle_sorting:
            self.setSortingEnabled(not self.isSortingEnabled())
Example #2
0
    def __init__(self, node, initial_topics=None, start_paused=False):
        super(PlotWidget, self).__init__()
        self.setObjectName('PlotWidget')

        self._node = node
        self._initial_topics = initial_topics

        _, package_path = get_resource('packages', 'rqt_plot')
        ui_file = os.path.join(package_path, 'share', '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(node)
        self.topic_edit.setCompleter(self._topic_completer)

        self._start_time = time.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)
Example #3
0
    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 = '/home/mohammad/Documents/CMU/RED/catkin_ws/src/rqt_safeguard/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()

        self.color_box.setStyleSheet("background-color: red;")

        # init and start update timer for plot
        self._update_timer = QTimer(self)
        self._update_timer.timeout.connect(self.update)
Example #4
0
    def _add_exclude_filter(self, filter_index=False):
        """
        :param filter_index: if false then this function shows a QMenu to allow the user to choose a
                             type of message filter. ''bool''
        OR
        :param filter_index: the index of the filter to be added, ''int''
        :return: if a filter was added then the index is returned, ''int''
        OR
        :return: if no filter was added then None is returned, ''NoneType''
        """
        if filter_index is False:
            filter_index = -1
            filter_select_menu = QMenu()
            for index in self._filter_factory_order:
                # flattens the _exclude filters list and only adds the item if it doesn't
                # already exist
                if index in ['message', 'location'] or \
                        not self.filter_factory[index][1] in \
                            [type(item) for sublist in self._exclude_filters for item in sublist]:
                    filter_select_menu.addAction(self.filter_factory[index][0])
            action = filter_select_menu.exec_(QCursor.pos())
            if action is None:
                return None
            for index in self._filter_factory_order:
                if self.filter_factory[index][0] == action.text():
                    filter_index = index
            if filter_index == -1:
                return None

        index = len(self._exclude_filters)
        newfilter = self.filter_factory[filter_index][1]()
        if len(self.filter_factory[filter_index]) >= 4:
            newwidget = self.filter_factory[filter_index][2](
                newfilter, self._rospack, self.filter_factory[filter_index][3])
        else:
            newwidget = self.filter_factory[filter_index][2](newfilter,
                                                             self._rospack)

        # pack the new filter tuple onto the filter list
        self._exclude_filters.append(
            (newfilter,
             FilterWrapperWidget(newwidget,
                                 self.filter_factory[filter_index][0]),
             filter_index))
        self._proxy_model.add_exclude_filter(newfilter)
        newfilter.filter_changed_signal.connect(
            self._proxy_model.handle_exclude_filters_changed)
        self._exclude_filters[index][1].delete_button.clicked.connect(
            self._delete_exclude_filter)
        self._model.rowsInserted.connect(
            self._exclude_filters[index][1].repopulate)

        # place the widget in the proper location
        self.exclude_table.insertRow(index)
        self.exclude_table.setCellWidget(index, 0,
                                         self._exclude_filters[index][1])
        self.exclude_table.resizeColumnsToContents()
        self.exclude_table.resizeRowsToContents()
        newfilter.filter_changed_signal.emit()
        return index
Example #5
0
    def add_plugin(self, plugin_descriptor):
        base_path = plugin_descriptor.attributes().get('plugin_path')

        menu_manager = self._plugin_menu_manager
        # create submenus
        for group in plugin_descriptor.groups():
            label = group['label']
            if menu_manager.contains_menu(label):
                submenu = menu_manager.get_menu(label)
            else:
                submenu = QMenu(label, menu_manager.menu)
                menu_action = submenu.menuAction()
                self._enrich_action(menu_action, group, base_path)
                menu_manager.add_item(submenu)
            menu_manager = MenuManager(submenu)
        # create action
        action_attributes = plugin_descriptor.action_attributes()
        action = QAction(action_attributes['label'], menu_manager.menu)
        self._enrich_action(action, action_attributes, base_path)

        self._plugin_mapper.setMapping(action, plugin_descriptor.plugin_id())
        action.triggered.connect(self._plugin_mapper.map)

        not_available = plugin_descriptor.attributes().get('not_available')
        if not_available:
            action.setEnabled(False)
            action.setStatusTip(
                self.tr('Plugin is not available: %s') % not_available)

        # add action to menu
        menu_manager.add_item(action)
    def __init__(self, initial_topics=None, start_paused=False):
        super(PlotWidget, self).__init__()
        self.setObjectName('PlotWidget')

        # Available ros topics for plotting
        # keys are i=InitSub, s=StateSub, r=RCSub, p=PathSub, w=WaypointSub,
        #          o=ObstacleSub, g=GPSDataSub, ci=ConInSub, cc=ConComSub
        self.message_dict = {
            'Course angle vs. Commanded': [('cc', 'chi_c'), ('s', 'chi')],
            'Roll angle vs. Commanded': [('ci', 'phi_c'), ('s', 'phi')],
            'Pitch angle vs. Commanded': [('s', 'theta'), ('ci', 'theta_c')],
            'Airspeed vs. Commanded': [('s', 'Va'), ('cc', 'Va_c')]
        }

        # # Available ros topics for plotting
        # self.message_dict = {
        #     'Course angle (rad)':'/state/chi',
        #     'Course angle commanded (rad)':'/controller_commands/chi_c',
        #     'Airspeed (m/s)':'/state/Va',
        #     'Angle of attack (rad)':'/state/alpha',
        #     'Slide slip angle (rad)':'/state/beta',
        #     'Roll angle (rad)':'/state/phi',
        #     'Pitch angle (rad)':'/state/theta',
        #     'Yaw angle (rad)':'/state/psi',
        #     'Body frame rollrate (rad/s)':'/state/p',
        #     'Body frame pitchrate (rad/s)':'/state/q',
        #     'Body frame yawrate (rad/s)':'/state/r',
        #     'Groundspeed (m/s)':'/state/Vg'
        #     }

        #self._initial_topics = initial_topics

        rp = rospkg.RosPack()
        ui_file = os.path.join(PWD, 'resources', 'plot.ui')
        loadUi(ui_file, self)

        self.pause_button.setIcon(QIcon.fromTheme('media-playback-pause'))
        self.clear_button.setIcon(QIcon.fromTheme('edit-clear'))
        self.data_plot = None

        if start_paused:
            self.pause_button.setChecked(True)

        self._start_time = rospy.get_time()
        self._rosdata = {}

        self._current_key = ''
        self._current_topics = []

        self._remove_topic_menu = QMenu()

        self._msgs.clear()
        self._msgs.addItems(self.message_dict.keys())

        self._msgs.currentIndexChanged[str].connect(
            self._draw_graph)  # <<<<<<< start here (also modify the dict)

        # init and start update timer for plot
        self._update_plot_timer = QTimer(self)
        self._update_plot_timer.timeout.connect(self.update_plot)
Example #7
0
    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('monitoring_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(True)
        if start_paused:
            self.pause_button.setChecked(True)

        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)

        rospy.Subscriber("/monitoring/gui", Gui,
                         self.monitoring_topic_overview_list_manager)
    def _define_menu(self):
        self._menu = QMenu(self._gl_view)

        layer_menu = QMenu('Layers', self._gl_view)
        for layer in self._mapDrawer.get_layers():
            layer_menu.addAction(layer.menu_action)
        self._menu.addMenu(layer_menu)
        self._menu.addSeparator()

        self._view2dAction = QAction(self._gl_view.tr("2D View"), self._gl_view, triggered=self._set_default_view)
        self._menu.addAction(self._view2dAction)

        self._view3dAction = QAction(self._gl_view.tr("3D View"), self._gl_view, triggered=self._set_3d_view)
        self._menu.addAction(self._view3dAction)
        self._menu.addSeparator()

        #self._rotateSubAction = QAction(self._gl_view.tr("Rotate with Sub"), self, checkable=True,
        #                       triggered=self._rotate_with_sub)
        #self._menu.addAction(self._rotateSubAction)

        self._lockOnSubAction = QAction(self._gl_view.tr("Lock on Sub"), self, checkable=True,
                                        triggered=self._lock_on_sub)
        self._menu.addAction(self._lockOnSubAction)
        self._menu.addSeparator()

        self._menu.addAction(QAction('Reset Path', self, triggered=self._mapDrawer.reset_path))

        setLocationAction = QAction('Set Location Target', self._gl_view, triggered=self._set_location_action)
        self._menu.addAction(setLocationAction)
Example #9
0
    def handle_header_view_customContextMenuRequested(self, pos):

        # create context menu
        menu = QMenu(self)

        action_toggle_auto_resize = menu.addAction('Auto-Resize')
        action_toggle_auto_resize.setCheckable(True)
        auto_resize_flag = (
            self.header().resizeMode(0) == QHeaderView.ResizeToContents)
        action_toggle_auto_resize.setChecked(auto_resize_flag)

        action_toggle_sorting = menu.addAction('Sorting')
        action_toggle_sorting.setCheckable(True)
        action_toggle_sorting.setChecked(self.isSortingEnabled())

        # show menu
        action = menu.exec_(self.header().mapToGlobal(pos))

        # evaluate user action
        if action is action_toggle_auto_resize:
            if auto_resize_flag:
                self.header().setResizeMode(QHeaderView.Interactive)
            else:
                self.header().setResizeMode(QHeaderView.ResizeToContents)

        elif action is action_toggle_sorting:
            self.setSortingEnabled(not self.isSortingEnabled())
Example #10
0
 def _gl_view_mouseReleaseEvent(self, event):
     if event.button() == Qt.RightButton:
         menu = QMenu(self._gl_view)
         action = QAction(self._gl_view.tr("Reset view"), self._gl_view)
         menu.addAction(action)
         action.triggered.connect(self._set_default_view)
         menu.exec_(self._gl_view.mapToGlobal(event.pos()))
Example #11
0
    def __init__(self, param_client, parameter, descriptor):
        super(EditorWidget, self).__init__()

        self._param_client = param_client
        self.parameter = parameter
        self.descriptor = descriptor

        self.cmenu = QMenu()
    def _on_header_menu(self, pos):
        header = self._widget.table_view.horizontalHeader()

        # Show context menu
        menu = QMenu(self._widget.table_view)
        action_toggle_auto_resize = menu.addAction('Toggle Auto-Resize')
        action = menu.exec_(header.mapToGlobal(pos))

        # Evaluate user action
        if action is action_toggle_auto_resize:
            if header.resizeMode(0) == QHeaderView.ResizeToContents:
                header.setSectionResizeMode(QHeaderView.Interactive)
            else:
                header.setSectionResizeMode(QHeaderView.ResizeToContents)
    def handle_header_view_customContextMenuRequested(self, pos):
        header = self.topics_tree_widget.header()

        # show context menu
        menu = QMenu(self)
        action_toggle_auto_resize = menu.addAction('Toggle Auto-Resize')
        action = menu.exec_(header.mapToGlobal(pos))

        # evaluate user action
        if action is action_toggle_auto_resize:
            if header.resizeMode(0) == QHeaderView.ResizeToContents:
                header.setResizeMode(QHeaderView.Interactive)
            else:
                header.setResizeMode(QHeaderView.ResizeToContents)
    def handle_header_view_customContextMenuRequested(self, pos):
        header = self.topics_tree_widget.header()

        # show context menu
        menu = QMenu(self)
        action_toggle_auto_resize = menu.addAction('Toggle Auto-Resize')
        action = menu.exec_(header.mapToGlobal(pos))

        # evaluate user action
        if action is action_toggle_auto_resize:
            if header.resizeMode(0) == QHeaderView.ResizeToContents:
                header.setResizeMode(QHeaderView.Interactive)
            else:
                header.setResizeMode(QHeaderView.ResizeToContents)
Example #15
0
    def _on_header_menu(self, pos):
        header = self._widget.table_view.horizontalHeader()

        # Show context menu
        menu = QMenu(self._widget.table_view)
        action_toggle_auto_resize = menu.addAction('Toggle Auto-Resize')
        action = menu.exec_(header.mapToGlobal(pos))

        # Evaluate user action
        if action is action_toggle_auto_resize:
            if header.resizeMode(0) == QHeaderView.ResizeToContents:
                header.setSectionResizeMode(QHeaderView.Interactive)
            else:
                header.setSectionResizeMode(QHeaderView.ResizeToContents)
Example #16
0
    def _rightclick_menu(self, event):
        """
        :type event: QEvent
        """

        # QTreeview.selectedIndexes() returns 0 when no node is selected.
        # This can happen when after booting no left-click has been made yet
        # (ie. looks like right-click doesn't count). These lines are the
        # workaround for that problem.
        selected = self._messages_tree.selectedIndexes()
        if len(selected) == 0:
            return

        menu = QMenu()
        text_action = QAction(self.tr('View Text'), menu)
        menu.addAction(text_action)
        raw_action = QAction(self.tr('View Raw'), menu)
        menu.addAction(raw_action)
        remove_action = QAction(self.tr('Remove message'), menu)
        menu.addAction(remove_action)

        action = menu.exec_(event.globalPos())

        if action == raw_action or action == text_action:
            rospy.logdebug('_rightclick_menu selected={}'.format(selected))
            selected_type = selected[1].data()

            if selected_type[-2:] == '[]':
                selected_type = selected_type[:-2]
            browsetext = None
            try:
                if (self._mode == rosmsg.MODE_MSG
                        or self._mode == rosaction.MODE_ACTION):
                    browsetext = rosmsg.get_msg_text(selected_type,
                                                     action == raw_action)
                elif self._mode == rosmsg.MODE_SRV:
                    browsetext = rosmsg.get_srv_text(selected_type,
                                                     action == raw_action)

                else:
                    raise
            except rosmsg.ROSMsgException as e:
                QMessageBox.warning(
                    self, self.tr('Warning'),
                    self.tr('The selected item component ' +
                            'does not have text to view.'))
            if browsetext is not None:
                self._browsers.append(
                    TextBrowseDialog(browsetext, self._rospack))
                self._browsers[-1].show()

        if action == remove_action:
            self._messages_tree.model().removeRow(selected[0].row())
Example #17
0
 def eventFilter(self, obj, event):
     if event.type() in self._event_callbacks:
         ret_val = self._event_callbacks[event.type()](obj, event)
         if ret_val is not None:
             return ret_val
     if event.type() == event.ContextMenu and obj == self.title_label:
         menu = QMenu(self)
         rename_action = menu.addAction(self.tr('Rename dock widget'))
         action = menu.exec_(self.mapToGlobal(event.pos()))
         if action == rename_action:
             self.title_label.hide()
             self.title_edit.setText(self.title_label.text())
             self.title_edit.show()
             self.title_edit.setFocus()
         return True
     return QObject.eventFilter(self, obj, event)
Example #18
0
    def _handle_column_right_click(self, pos):
        menu = QMenu(self)
        hide = menu.addAction('Hide Column')
        showall = menu.addAction('Show all columns')

        # Don't allow hiding the last column
        if self.table_view.horizontalHeader().count() - self.table_view.horizontalHeader().hiddenSectionCount() == 1:
            hide.setEnabled(False)

        ac = menu.exec_(self.table_view.horizontalHeader().mapToGlobal(pos))
        if ac == hide:
            column = self.table_view.horizontalHeader().logicalIndexAt(pos.x())
            self.table_view.horizontalHeader().hideSection(column)
        elif ac == showall:
            for i in range(self.table_view.horizontalHeader().count()):
                self.table_view.horizontalHeader().showSection(i)
Example #19
0
    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)
Example #20
0
    def __init__(self, updater, config):
        """
        @param updater: A class that extends threading.Thread.
        @type updater: rqt_reconfigure.param_updater.ParamUpdater
        """
        super(EditorWidget, self).__init__()

        self._updater = updater
        self.param_name = config['name']
        self.param_default = config['default']
        self.param_description = config['description']

        self.old_value = None

        self.cmenu = QMenu()
        self.cmenu.addAction(self.tr('Set to Default')).triggered.connect(
            self._set_to_default)
    def _add_exclude_filter(self, filter_index=False):
        """
        :param filter_index: if false then this function shows a QMenu to allow the user to choose a type of message filter. ''bool''
        OR
        :param filter_index: the index of the filter to be added, ''int''
        :return: if a filter was added then the index is returned, ''int''
        OR
        :return: if no filter was added then None is returned, ''NoneType''
        """
        if filter_index is False:
            filter_index = -1
            filter_select_menu = QMenu()
            for index in self._filter_factory_order:
                # flattens the _exclude filters list and only adds the item if it doesn't already exist
                if index in ['message', 'location'] or not self.filter_factory[index][1] in [type(item) for sublist in self._exclude_filters for item in sublist]:
                    filter_select_menu.addAction(self.filter_factory[index][0])
            action = filter_select_menu.exec_(QCursor.pos())
            if action is None:
                return None
            for index in self._filter_factory_order:
                if self.filter_factory[index][0] == action.text():
                    filter_index = index
            if filter_index == -1:
                return None

        index = len(self._exclude_filters)
        newfilter = self.filter_factory[filter_index][1]()
        if len(self.filter_factory[filter_index]) >= 4:
            newwidget = self.filter_factory[filter_index][2](newfilter, self._rospack, self.filter_factory[filter_index][3])
        else:
            newwidget = self.filter_factory[filter_index][2](newfilter, self._rospack)

        # pack the new filter tuple onto the filter list
        self._exclude_filters.append((newfilter, FilterWrapperWidget(newwidget, self.filter_factory[filter_index][0]), filter_index))
        self._proxy_model.add_exclude_filter(newfilter)
        newfilter.filter_changed_signal.connect(self._proxy_model.handle_exclude_filters_changed)
        self._exclude_filters[index][1].delete_button.clicked.connect(self._delete_exclude_filter)
        self._model.rowsInserted.connect(self._exclude_filters[index][1].repopulate)

        # place the widget in the proper location
        self.exclude_table.insertRow(index)
        self.exclude_table.setCellWidget(index, 0, self._exclude_filters[index][1])
        self.exclude_table.resizeColumnsToContents()
        self.exclude_table.resizeRowsToContents()
        newfilter.filter_changed_signal.emit()
        return index
Example #22
0
    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
Example #23
0
class MenuDashWidget(IconToolButton):
    """
    A widget which displays a pop-up menu when clicked

    :param name: The name to give this widget.
    :type name: str
    :param icon: The icon to display in this widgets button.
    :type icon: str
    """
    def __init__(self, name, icons=None, clicked_icons=None, icon_paths=[]):
        if icons == None:
            icons = [['bg-grey.svg', 'ic-motors.svg']]
        super(MenuDashWidget, self).__init__(name,
                                             icons=icons,
                                             suppress_overlays=True,
                                             icon_paths=icon_paths)
        self.setStyleSheet(
            'QToolButton::menu-indicator {image: url(none.jpg);} QToolButton {border: none;}'
        )
        self.setPopupMode(QToolButton.InstantPopup)
        self.update_state(0)

        self.pressed.disconnect(self._pressed)
        self.released.disconnect(self._released)

        self._menu = QMenu()
        self._menu.aboutToHide.connect(self._released)
        self._menu.aboutToShow.connect(self._pressed)

        self.setMenu(self._menu)

    def add_separator(self):
        return self._menu.addSeparator()

    def add_action(self, name, callback):
        """
        Add an action to the menu, and return the newly created action.

        :param name: The name of the action.
        :type name: str
        :param callback: Function to be called when this item is pressed.
        :type callback: callable
        """
        return self._menu.addAction(name, callback)
Example #24
0
    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 _rightclick_menu(self, event):
        """
        :type event: QEvent
        """

        # QTreeview.selectedIndexes() returns 0 when no node is selected.
        # This can happen when after booting no left-click has been made yet
        # (ie. looks like right-click doesn't count). These lines are the
        # workaround for that problem.
        selected = self._messages_tree.selectedIndexes()
        if len(selected) == 0:
            return

        menu = QMenu()
        text_action = QAction(self.tr('View Text'), menu)
        menu.addAction(text_action)
        raw_action = QAction(self.tr('View Raw'), menu)
        menu.addAction(raw_action)
        remove_action = QAction(self.tr('Remove message'), menu)
        menu.addAction(remove_action)

        action = menu.exec_(event.globalPos())

        if action == raw_action or action == text_action:
            rospy.logdebug('_rightclick_menu selected={}'.format(selected))
            selected_type = selected[1].data()

            if selected_type[-2:] == '[]':
                selected_type = selected_type[:-2]
            browsetext = None
            try:
                if (self._mode == rosmsg.MODE_MSG or
                    self._mode == rosaction.MODE_ACTION):
                    browsetext = rosmsg.get_msg_text(selected_type,
                                                     action == raw_action)
                elif self._mode == rosmsg.MODE_SRV:
                    browsetext = rosmsg.get_srv_text(selected_type,
                                                     action == raw_action)

                else:
                    raise
            except rosmsg.ROSMsgException as e:
                QMessageBox.warning(self, self.tr('Warning'),
                                    self.tr('The selected item component ' +
                                            'does not have text to view.'))
            if browsetext is not None:
                self._browsers.append(TextBrowseDialog(browsetext,
                                                       self._rospack))
                self._browsers[-1].show()

        if action == remove_action:
            self._messages_tree.model().removeRow(selected[0].row())
    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)
Example #27
0
    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)
Example #28
0
    def __init__(self, name, icons=None, clicked_icons=None, icon_paths=[]):
        if icons == None:
            icons = [['bg-grey.svg', 'ic-motors.svg']]
        super(MenuDashWidget, self).__init__(name,
                                             icons=icons,
                                             suppress_overlays=True,
                                             icon_paths=icon_paths)
        self.setStyleSheet(
            'QToolButton::menu-indicator {image: url(none.jpg);} QToolButton {border: none;}'
        )
        self.setPopupMode(QToolButton.InstantPopup)
        self.update_state(0)

        self.pressed.disconnect(self._pressed)
        self.released.disconnect(self._released)

        self._menu = QMenu()
        self._menu.aboutToHide.connect(self._released)
        self._menu.aboutToShow.connect(self._pressed)

        self.setMenu(self._menu)
Example #29
0
 def _gl_view_mouseReleaseEvent(self, event):
     if event.button() == Qt.RightButton:
         menu = QMenu(self._gl_view)
         action = QAction(self._gl_view.tr("Reset view"), self._gl_view)
         menu.addAction(action)
         action.triggered.connect(self._set_default_view)
         menu.exec_(self._gl_view.mapToGlobal(event.pos()))
class MenuDashWidget(IconToolButton):
    """
    A widget which displays a pop-up menu when clicked

    :param name: The name to give this widget.
    :type name: str
    :param icon: The icon to display in this widgets button.
    :type icon: str
    """
    def __init__(self, name, icons=None, clicked_icons=None, icon_paths=[]):
        if icons == None:
            icons = [['bg-grey.svg', 'ic-motors.svg']]
        super(MenuDashWidget, self).__init__(name, icons=icons, suppress_overlays=True, icon_paths=icon_paths)
        self.setStyleSheet('QToolButton::menu-indicator {image: url(none.jpg);} QToolButton {border: none;}')
        self.setPopupMode(QToolButton.InstantPopup)
        self.update_state(0)

        self.pressed.disconnect(self._pressed)
        self.released.disconnect(self._released)

        self._menu = QMenu()
        self._menu.aboutToHide.connect(self._released)
        self._menu.aboutToShow.connect(self._pressed)

        self.setMenu(self._menu)

    def add_separator(self):
        return self._menu.addSeparator()

    def add_action(self, name, callback):
        """
        Add an action to the menu, and return the newly created action.

        :param name: The name of the action.
        :type name: str
        :param callback: Function to be called when this item is pressed.
        :type callback: callable
        """
        return self._menu.addAction(name, callback)
    def _on_ctrl_menu(self, pos):
        # Get data of selected controller
        row = self._widget.table_view.rowAt(pos.y())
        if row < 0:
            return  # Cursor is not under a valid item

        ctrl = self._controllers[row]

        # Show context menu
        menu = QMenu(self._widget.table_view)
        if ctrl.state == 'running':
            action_stop = menu.addAction(self._icons['stopped'], 'Stop')
            action_kill = menu.addAction(self._icons['uninitialized'],
                                         'Stop and Unload')
        elif ctrl.state == 'stopped':
            action_start = menu.addAction(self._icons['running'], 'Start')
            action_unload = menu.addAction(self._icons['uninitialized'],
                                           'Unload')
        elif ctrl.state == 'uninitialized':
            action_load = menu.addAction(self._icons['stopped'], 'Load')
            action_spawn = menu.addAction(self._icons['running'],
                                          'Load and Start')

        action = menu.exec_(self._widget.table_view.mapToGlobal(pos))

        # Evaluate user action
        if ctrl.state == 'running':
            if action is action_stop:
                self._stop_controller(ctrl.name)
            elif action is action_kill:
                self._stop_controller(ctrl.name)
                self._unload_controller(ctrl.name)
        elif ctrl.state == 'stopped':
            if action is action_start:
                self._start_controller(ctrl.name)
            elif action is action_unload:
                self._unload_controller(ctrl.name)
        elif ctrl.state == 'uninitialized':
            if action is action_load:
                self._load_controller(ctrl.name)
            if action is action_spawn:
                self._load_controller(ctrl.name)
                self._start_controller(ctrl.name)
    def _define_menu(self):
        self._menu = QMenu(self.imageFrame)

        configureAction = QAction("Configure ...", self.imageFrame, triggered=self.configure_filterchain_action)
        self._menu.addAction(configureAction)
        self._menu.addSeparator()
        self._recordAction = QAction("Record ...", self.imageFrame, triggered=self.record_execution_action)
        self._menu.addAction(self._recordAction)
        self._stop_recordAction = QAction("Stop Record", self.imageFrame, triggered=self.stop_record_execution_action)
        self._stop_recordAction.setEnabled(False)
        self._menu.addAction(self._stop_recordAction)
        self._menu.addSeparator()

        deleteAction = QAction(self.imageFrame.tr("Delete this execution"), self.imageFrame, triggered=self.delete_current_execution)
        self._menu.addAction(deleteAction)
    def __init__(self, name, icons=None, clicked_icons=None, icon_paths=[]):
        if icons == None:
            icons = [['bg-grey.svg', 'ic-motors.svg']]
        super(MenuDashWidget, self).__init__(name, icons=icons, suppress_overlays=True, icon_paths=icon_paths)
        self.setStyleSheet('QToolButton::menu-indicator {image: url(none.jpg);} QToolButton {border: none;}')
        self.setPopupMode(QToolButton.InstantPopup)
        self.update_state(0)

        self.pressed.disconnect(self._pressed)
        self.released.disconnect(self._released)

        self._menu = QMenu()
        self._menu.aboutToHide.connect(self._released)
        self._menu.aboutToShow.connect(self._pressed)

        self.setMenu(self._menu)
    def __init__(self, updater, config):
        '''
        @param updater: A class that extends threading.Thread.
        @type updater: rqt_reconfigure.param_updater.ParamUpdater
        '''

        super(EditorWidget, self).__init__()

        self._updater = updater
        self.param_name = config['name']
        self.param_default = config['default']
        self.param_description = config['description']

        self.old_value = None

        self.cmenu = QMenu()
        self.cmenu.addAction(self.tr('Set to Default')).triggered.connect(self._set_to_default)
    def _on_ctrl_menu(self, pos):
        # Get data of selected controller
        row = self._widget.table_view.rowAt(pos.y())
        if row < 0:
            return  # Cursor is not under a valid item

        ctrl = self._controllers[row]

        # Show context menu
        menu = QMenu(self._widget.table_view)
        if ctrl.state == 'running':
            action_stop = menu.addAction(self._icons['stopped'], 'Stop')
            action_kill = menu.addAction(self._icons['uninitialized'],
                                         'Stop and Unload')
        elif ctrl.state == 'stopped':
            action_start = menu.addAction(self._icons['running'], 'Start')
            action_unload = menu.addAction(self._icons['uninitialized'],
                                           'Unload')
        elif ctrl.state == 'uninitialized':
            action_load = menu.addAction(self._icons['stopped'], 'Load')
            action_spawn = menu.addAction(self._icons['running'],
                                          'Load and Start')

        action = menu.exec_(self._widget.table_view.mapToGlobal(pos))

        # Evaluate user action
        if ctrl.state == 'running':
            if action is action_stop:
                self._stop_controller(ctrl.name)
            elif action is action_kill:
                self._stop_controller(ctrl.name)
                self._unload_controller(ctrl.name)
        elif ctrl.state == 'stopped':
            if action is action_start:
                self._start_controller(ctrl.name)
            elif action is action_unload:
                self._unload_controller(ctrl.name)
        elif ctrl.state == 'uninitialized':
            if action is action_load:
                self._load_controller(ctrl.name)
            if action is action_spawn:
                self._load_controller(ctrl.name)
                self._start_controller(ctrl.name)
Example #36
0
    def __init__(self,
                 widget_name='PlotWidget',
                 initial_topics=None,
                 start_paused=False):
        # print("Iniitial topics have been set, starting...\n")
        super(PlotWidget, self).__init__()
        # print("widget_name", widget_name)
        self.setObjectName(widget_name)

        self._initial_topics = initial_topics

        rp = rospkg.RosPack()
        ui_file = os.path.join(rp.get_path('sbgc_plot'), 'resource',
                               widget_name + '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)
Example #37
0
 def show_context_menu(self, point):
     menu = QMenu(self)
     waypoint_action = menu.addAction("Add Waypoint")
     replace_action = menu.addAction("Replace all waypoints")
     land_action = menu.addAction("Land here")
     clear_action = menu.addAction("Clear all waypoints")
     choice = menu.exec_(self.mapToGlobal(point))
     clickX = point.x()
     clickY = point.y()
     lon = GoogleMapPlotter.pix_to_rel_lon(self.GMP.west, clickX,
                                           self.GMP.zoom)
     lat = GoogleMapPlotter.pix_to_rel_lat(self.GMP.north, clickY,
                                           self.GMP.zoom)
     n, e, d = PPPub.getNED(lat, lon)
     if choice == waypoint_action:
         self.add_waypoint(n, e, d)
     elif choice == replace_action:
         self.replace_waypoints(n, e, d)
     elif choice == clear_action:
         self.clear_waypoints()
     elif choice == land_action:
         self.add_land_waypoint([n, e, 0])
class VisionMainWidget(QWidget):
    def __init__(self):
        super(VisionMainWidget, self).__init__()
        try:
            rospy.wait_for_service('/provider_vision/get_information_list', timeout=2)
            rospy.wait_for_service('/provider_vision/get_filterchain_from_execution', timeout=2)
            rospy.wait_for_service('/provider_vision/get_media_from_execution', timeout=2)
            rospy.wait_for_service('/provider_vision/execute_cmd', timeout=2)
        except rospy.ROSException:
            rospy.loginfo('Services unavailable')
        ui_file = os.path.join(rospkg.RosPack().get_path('rqt_vision'), 'resource', 'mainwidget.ui')
        loadUi(ui_file, self)
        self.setWindowTitle('Vision UI')

        self._current_execution = None
        self._current_execution_subscriber = None
        self._current_execution_subscriber_result = None
        self._is_recording = False
        self._video_writer = None
        self._cv_image = None
        self._widget = None
        self.bridge = CvBridge()
        self.connect(self, SIGNAL("result_change(QString)"), self._handle_result)
        ##### Service
        self._srv_get_information_list = rospy.ServiceProxy('/provider_vision/get_information_list', get_information_list)
        self._srv_get_filterchain_from_execution = rospy.ServiceProxy('/provider_vision/get_filterchain_from_execution', get_filterchain_from_execution)
        self._srv_get_media_from_execution = rospy.ServiceProxy('/provider_vision/get_media_from_execution', get_media_from_execution)
        self._srv_execute_cmd = rospy.ServiceProxy('/provider_vision/execute_cmd', execute_cmd)

        ###
        self.image_frame_mouse_release_event_original = self.imageFrame.mouseReleaseEvent
        self.imageFrame.mouseReleaseEvent = self.image_frame_mouse_release_event

        self.refresh_button.clicked[bool].connect(self.fill_execution_list)
        self.current_execution.currentIndexChanged[int].connect(self.current_execution_index_changed)
        self.image_paint_event_original = self.imageFrame.paintEvent
        self.imageFrame.paintEvent = self.image_paint_event
        self.fill_execution_list()
        self._define_menu()

    def _define_menu(self):
        self._menu = QMenu(self.imageFrame)

        configureAction = QAction("Configure ...", self.imageFrame, triggered=self.configure_filterchain_action)
        self._menu.addAction(configureAction)
        self._menu.addSeparator()
        self._recordAction = QAction("Record ...", self.imageFrame, triggered=self.record_execution_action)
        self._menu.addAction(self._recordAction)
        self._stop_recordAction = QAction("Stop Record", self.imageFrame, triggered=self.stop_record_execution_action)
        self._stop_recordAction.setEnabled(False)
        self._menu.addAction(self._stop_recordAction)
        self._menu.addSeparator()

        deleteAction = QAction(self.imageFrame.tr("Delete this execution"), self.imageFrame, triggered=self.delete_current_execution)
        self._menu.addAction(deleteAction)


    def fill_execution_list(self):
        self._refresh_clean()
        self._current_execution = None
        self.current_execution.clear()

        execution_string = self._srv_get_information_list(1)
        execution_list = execution_string.list.split(';')
        if len(execution_list) == 0:
            return
        self._current_execution = execution_list[0]
        for execution in execution_list:
            if len(execution) > 0:
                self.current_execution.addItem(execution)

    def current_execution_index_changed(self, index):
        self._refresh_clean()

        if self._current_execution_subscriber is not None:
            self._current_execution_subscriber.unregister()
            self._current_execution_subscriber_result.unregister()

        new_execution = self.current_execution.itemText(index)
        self._current_execution = new_execution
        self._filterchain = self._srv_get_filterchain_from_execution(self._current_execution)
        self._current_execution_subscriber = rospy.Subscriber('/provider_vision/' + new_execution + '_image',
                                                              SensorImage, self.current_execution_callback)
        self._current_execution_subscriber_result = rospy.Subscriber('/provider_vision/' + new_execution + '_result',
                                                                     VisionTarget,
                                                                     self.current_execution_result_callback)


    def _refresh_clean(self):
        if self._current_execution_subscriber is not None:
            self._current_execution_subscriber.unregister()
            self._current_execution_subscriber_result.unregister()
        self.result_text.setText('')
        self._cv_image = None
        self.imageFrame.update()

    def current_execution_callback(self, img):
        try:
            cv_image = self.bridge.imgmsg_to_cv2(img, desired_encoding="rgb8")
            height, width, channel = cv_image.shape
            bytesPerLine = 3 * width
            self._cv_image = QImage(cv_image.data, width, height, bytesPerLine, QImage.Format_RGB888)

            if self._is_recording:
                if self._video_writer is None:
                    four_cc = cv2.cv.CV_FOURCC(*'HFYU')
                    self._video_writer = cv2.VideoWriter(self._recording_file_name, four_cc, float(15), (width,height))
                temp = cv2.cvtColor(cv_image,cv2.cv.CV_BGR2RGB)
                self._video_writer.write(temp)
        except CvBridgeError as e:
            print(e)
        self.imageFrame.update()

    def image_paint_event(self, data):
        self.image_paint_event_original(data)
        if self._cv_image is None:
            return;
        img = self._cv_image

        painter = QPainter(self.imageFrame)
        painter.drawImage(data.rect(), img)
        painter.end()

    def current_execution_result_callback(self, visionTarget):
        result = 'X:{}, Y:{}, width:{:.2f}, height:{:.2f}, angle:{:.2f}, desc_1:{}, desc_2:{}'.format(visionTarget.x,
                                                                                                      visionTarget.y,
                                                                                                      visionTarget.width,
                                                                                                      visionTarget.height,
                                                                                                      visionTarget.angle,
                                                                                                      visionTarget.desc_1,
                                                                                                      visionTarget.desc_2)
        self.emit(SIGNAL("result_change(QString)"), result)

    def _handle_result(self,result):
        self.result_text.setText(result)

    def image_frame_mouse_release_event(self,event):
        if event.button() == Qt.RightButton:
            self._menu.exec_(self.imageFrame.mapToGlobal(event.pos()))

    def delete_current_execution(self):

        if self._current_execution is None :
            return

        media = self._srv_get_media_from_execution(self._current_execution)

        self._srv_execute_cmd(self._current_execution,self._filterchain.list,media.list,2)

        self.fill_execution_list()

    def configure_filterchain_action(self):
        self._widget = ConfigureFilterchainWidget(self._current_execution, self._filterchain)
        self._widget.show()

    def shutdown_plugin(self):
        if self._current_execution_subscriber is not None:
            self._current_execution_subscriber.unregister()
            self._current_execution_subscriber_result.unregister()
        if self._widget is not None:
            self._widget.close()

    def record_execution_action(self):
        Tk().withdraw()
        filename = asksaveasfilename(defaultextension='.avi')
        self._recording_file_name = filename
        if len(self._recording_file_name) > 0:
            self._is_recording = True
            self._recordAction.setEnabled(False)
            self._stop_recordAction.setEnabled(True)

    def stop_record_execution_action(self):
        self._is_recording = False
        time.sleep(0.1)
        self._video_writer.release()
        self._video_writer = None
        self._recordAction.setEnabled(True)
        self._stop_recordAction.setEnabled(False)
Example #39
0
class PlotWidget(QWidget):
    _interval = 500

    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 = '/home/mohammad/Documents/CMU/RED/catkin_ws/src/rqt_safeguard/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()

        self.color_box.setStyleSheet("background-color: red;")

        # init and start update timer for plot
        self._update_timer = QTimer(self)
        self._update_timer.timeout.connect(self.update)

    # def switch_data_plot_widget(self, data_plot):
    #     self.enable_timer(enabled=False)

    #     self.data_plot_layout.removeWidget(self.data_plot)
    #     if self.data_plot is not None:
    #         self.data_plot.close()

    #     self.data_plot = data_plot
    #     self.data_plot_layout.addWidget(self.data_plot)
    #     self.data_plot.autoscroll(self.autoscroll_checkbox.isChecked())

    #     # setup drag 'n drop
    #     self.data_plot.dropEvent = self.dropEvent
    #     self.data_plot.dragEnterEvent = self.dragEnterEvent

    #     if self._initial_topics:
    #         for topic_name in self._initial_topics:
    #             self.add_topic(topic_name)
    #         self._initial_topics = None
    #     else:
    #         for topic_name, rosdata in self._rosdata.items():
    #             data_x, data_y = rosdata.next()
    #             self.data_plot.add_curve(topic_name, topic_name, data_x, data_y)

    #     self._subscribed_topics_changed()

    @Slot('QDragEnterEvent*')
    def dragEnterEvent(self, event):
        # get topic name
        if not event.mimeData().hasText():
            if not hasattr(event.source(), 'selectedItems') or len(
                    event.source().selectedItems()) == 0:
                qWarning(
                    'Plot.dragEnterEvent(): not hasattr(event.source(), selectedItems) or len(event.source().selectedItems()) == 0'
                )
                return
            item = event.source().selectedItems()[0]
            topic_name = item.data(0, Qt.UserRole)
            if topic_name == None:
                qWarning(
                    'Plot.dragEnterEvent(): not hasattr(item, ros_topic_name_)'
                )
                return
        else:
            topic_name = str(event.mimeData().text())

        # check for plottable field type
        plottable, message = is_plottable(topic_name)
        if plottable:
            event.acceptProposedAction()
        else:
            qWarning('Plot.dragEnterEvent(): rejecting: "%s"' % (message))

    @Slot('QDropEvent*')
    def dropEvent(self, event):
        if event.mimeData().hasText():
            topic_name = str(event.mimeData().text())
        else:
            droped_item = event.source().selectedItems()[0]
            topic_name = str(droped_item.data(0, Qt.UserRole))
        self.add_topic(topic_name)

    @Slot(str)
    def on_topic_edit_textChanged(self, topic_name):
        # on empty topic name, update topics
        if topic_name in ('', '/'):
            self._topic_completer.update_topics()

        plottable, message = is_plottable(topic_name)
        self.subscribe_topic_button.setEnabled(plottable)
        self.subscribe_topic_button.setToolTip(message)

    @Slot()
    def on_topic_edit_returnPressed(self):
        if self.subscribe_topic_button.isEnabled():
            self.add_topic(str(self.topic_edit.text()))

    @Slot()
    def on_subscribe_topic_button_clicked(self):
        self.add_topic(str(self.topic_edit.text()))

    @Slot(bool)
    def on_pause_button_clicked(self, checked):
        self.enable_timer(not checked)
        print("pause")

    @Slot(bool)
    def on_autoscroll_checkbox_clicked(self, checked):
        # self.data_plot.autoscroll(checked)
        if checked:
            # self.data_plot.redraw()
            print("checked is clicked")

    # @Slot()
    # def on_clear_button_clicked(self):
    #     print("Clear Button is clicked")
    #     #self.clear_plot()

    def update(self):
        print("update")

        for topic_name, rosdata in self._rosdata.items():
            decision, oriX = rosdata.next_dx()
            if oriX:
                self.oriX.setText(str(round(oriX, 2)))
            oriY, oriZ = rosdata.next_yz()
            if oriY:
                self.oriY.setText(str(round(oriY, 2)))
            if oriZ:
                self.oriZ.setText(str(round(oriZ, 2)))
            placX, placY = rosdata.next_pxy()
            if placX:
                self.placX.setText(str(round(100 * placX, 2)))
            if placY:
                self.placY.setText(str(round(100 * placY, 2)))
            placZ = rosdata.next_pz()
            if placZ:
                self.placZ.setText(str(round(100 * placZ, 2)))

        if decision:
            print(decision)
            self.color_box.setStyleSheet(
                "background-color: red; color: white; font: bold; font-size: 96px;"
            )
            self.color_box.setText("Not Safe")
        else:
            print(decision)
            self.color_box.setStyleSheet(
                "background-color: green; color: white; font: bold; font-size: 96px;"
            )
            self.color_box.setText("Safe")
        # if self.data_plot is not None:
        #     needs_redraw = False
        #     for topic_name, rosdata in self._rosdata.items():
        #         try:
        #             data_x, data_y = rosdata.next()
        #             if data_x or data_y:
        #                 self.data_plot.update_values(topic_name, data_x, data_y)
        #                 needs_redraw = True
        #         except RosPlotException as e:
        #             qWarning('PlotWidget.update_plot(): error in rosplot: %s' % e)
        #     if needs_redraw:
        #         self.data_plot.redraw()

    def _subscribed_topics_changed(self):
        self._update_remove_topic_menu()
        if not self.pause_button.isChecked():
            # if pause button is not pressed, enable timer based on subscribed topics
            self.enable_timer()
            print("if not self.pause_button.isChecked(): IN WIDGET PY")
        #self.data_plot.redraw()

    def _update_remove_topic_menu(self):
        def make_remove_topic_function(x):
            return lambda: self.remove_topic(x)

        self._remove_topic_menu.clear()
        for topic_name in sorted(self._rosdata.keys()):
            action = QAction(topic_name, self._remove_topic_menu)
            action.triggered.connect(make_remove_topic_function(topic_name))
            self._remove_topic_menu.addAction(action)

        if len(self._rosdata) > 1:
            all_action = QAction('All', self._remove_topic_menu)
            all_action.triggered.connect(self.clean_up_subscribers)
            self._remove_topic_menu.addAction(all_action)

        self.remove_topic_button.setMenu(self._remove_topic_menu)

    def add_topic(self, topic_name):
        self.enable_timer()
        topics_changed = False
        for topic_name in get_plot_fields(topic_name)[0]:
            if topic_name in self._rosdata:
                qWarning(
                    'PlotWidget.add_topic(): topic already subscribed: %s' %
                    topic_name)
                continue
            self._rosdata[topic_name] = ROSData(topic_name, self._start_time)
            if self._rosdata[topic_name].error is not None:
                qWarning(str(self._rosdata[topic_name].error))
                del self._rosdata[topic_name]
            else:
                # data_x, data_y = self._rosdata[topic_name].next()                          INJA TAGHIR BEDE UPDATE KON MAGHADIR RO
                #self.data_plot.add_curve(topic_name, topic_name, data_x, data_y)
                topics_changed = True

        if topics_changed:
            self._subscribed_topics_changed()

    def remove_topic(self, topic_name):
        self._rosdata[topic_name].close()
        del self._rosdata[topic_name]
        # self.data_plot.remove_curve(topic_name)

        self._subscribed_topics_changed()

    # def clear_plot(self):
    #     for topic_name, _ in self._rosdata.items():
    #         self.data_plot.clear_values(topic_name)
    #     self.data_plot.redraw()

    def clean_up_subscribers(self):
        for topic_name, rosdata in self._rosdata.items():
            rosdata.close()
            # self.data_plot.remove_curve(topic_name)
        self._rosdata = {}

        self._subscribed_topics_changed()

    def enable_timer(self, enabled=True):
        if enabled:
            self._update_timer.start(self._interval)
        else:
            self._update_timer.stop()

    def alaki(self):
        print("alaki")
class NavigationMapWidget(QWidget):
    def __init__(self, plugin):
        super(NavigationMapWidget, self).__init__()
        rp = rospkg.RosPack()
        try:
            rospy.wait_for_service('/proc_control/set_global_target', timeout=2)
        except rospy.ROSException:
            False

        ui_file = os.path.join(rp.get_path('rqt_navigation_map'), 'resource', 'mainWidget.ui')
        loadUi(ui_file, self)
        self._plugin = plugin

        self._topic_name = None
        self._odom_subscriber = None

        # create GL view
        self._gl_view = GLWidget()
        self._gl_view.unsetCursor()
        self._mapDrawer = MapDrawer(self)

        self._position = (0.0, 0.0, 0.0)
        self._mapDrawer.set_position(self._position)
        self._orientation = quaternion_about_axis(45.0, (0.0, 0.0, 1.0))
        self._mapDrawer.set_orientation(self._orientation,45)
        # add GL view to widget layout
        self.layout().addWidget(self._gl_view)

        self._rotate_with_sub_activated = False
        self._lock_on_sub_activated = False
        self._yaw = 0

        self._odom_subscriber = rospy.Subscriber('/proc_navigation/odom', Odometry, self._odom_callback)
        self.position_target_subscriber = rospy.Subscriber('/proc_control/current_target', PositionTarget,
                                                           self._position_target_callback)

        self.set_global_target = rospy.ServiceProxy('/proc_control/set_global_target', SetPositionTarget)

        self._define_menu()

    def _define_menu(self):
        self._menu = QMenu(self._gl_view)

        layer_menu = QMenu('Layers', self._gl_view)
        for layer in self._mapDrawer.get_layers():
            layer_menu.addAction(layer.menu_action)
        self._menu.addMenu(layer_menu)
        self._menu.addSeparator()

        self._view2dAction = QAction(self._gl_view.tr("2D View"), self._gl_view, triggered=self._set_default_view)
        self._menu.addAction(self._view2dAction)

        self._view3dAction = QAction(self._gl_view.tr("3D View"), self._gl_view, triggered=self._set_3d_view)
        self._menu.addAction(self._view3dAction)
        self._menu.addSeparator()

        #self._rotateSubAction = QAction(self._gl_view.tr("Rotate with Sub"), self, checkable=True,
        #                       triggered=self._rotate_with_sub)
        #self._menu.addAction(self._rotateSubAction)

        self._lockOnSubAction = QAction(self._gl_view.tr("Lock on Sub"), self, checkable=True,
                                        triggered=self._lock_on_sub)
        self._menu.addAction(self._lockOnSubAction)
        self._menu.addSeparator()

        self._menu.addAction(QAction('Reset Path', self, triggered=self._mapDrawer.reset_path))

        setLocationAction = QAction('Set Location Target', self._gl_view, triggered=self._set_location_action)
        self._menu.addAction(setLocationAction)

    def _position_target_callback(self, target):
        self._mapDrawer.drawTarget(target.X, target.Y, target.Z)

    def _odom_callback(self, odom_data):
        vehicle_position_x = odom_data.pose.pose.position.x
        vehicle_position_y = odom_data.pose.pose.position.y
        vehicle_position_z = odom_data.pose.pose.position.z
        self._position = (vehicle_position_x, vehicle_position_y, vehicle_position_z)
        self._mapDrawer.set_position(self._position)
        self._yaw = odom_data.pose.pose.orientation.z
        self._orientation = quaternion_about_axis(math.radians(self._yaw), (0.0, 0.0, 1.0))
        self._mapDrawer.set_orientation(self._orientation,self._yaw)

    def save_settings(self, plugin_settings, instance_settings):
        self._mapDrawer.save_settings(plugin_settings,instance_settings)
        view_matrix_string = repr(self._gl_view.get_view_matrix())
        instance_settings.set_value('view_matrix', view_matrix_string)
        instance_settings.set_value('lock_on_sub_activated', str(self._lock_on_sub_activated))

    def restore_settings(self, plugin_settings, instance_settings):
        self._mapDrawer.restore_settings(plugin_settings,instance_settings)
        view_matrix_string = instance_settings.value('view_matrix')
        try:
            view_matrix = eval(view_matrix_string)
        except Exception:
            view_matrix = None

        if view_matrix is not None:
            self._gl_view.set_view_matrix(view_matrix)
        else:
            self._set_default_view()

        lock_on_sub = instance_settings.value('lock_on_sub_activated') == 'True'
        if lock_on_sub is None:
            print 'Nothing stored for lock_on_sub'
        else:
            self._lock_on_sub(lock_on_sub)
            self._lockOnSubAction.setChecked(lock_on_sub)

        #rotate_with_sub = instance_settings.value('rotate_with_sub_activated') == 'True'
        #if rotate_with_sub is None:
        #    print 'Nothing stored for lock_on_sub'
        #else:
        #    self._rotate_with_sub(rotate_with_sub)
        #    self._rotateSubAction.setChecked(rotate_with_sub)

    def _set_default_view(self):
        self._gl_view.makeCurrent()
        self._gl_view.reset_view()
        self._gl_view.translate((0, 0, -800))

    def _set_3d_view(self):
        self._gl_view.makeCurrent()
        self._gl_view.reset_view()
        self._gl_view.rotate((0, 0, 1), 0)
        self._gl_view.rotate((1, 0, 0), -75)
        self._gl_view.translate((-100, -100, -500))

    def _rotate_with_sub(self, checked):
        self._rotate_with_sub_activated = checked
        self._mapDrawer.set_rotate_with_sub_activated(checked)

    def _lock_on_sub(self, checked):
        self._lock_on_sub_activated = checked
        self._mapDrawer.set_lock_on_sub_activated(checked)

        self._view2dAction.setEnabled(not checked)
        self._view3dAction.setEnabled(not checked)


    def _gl_view_mouseReleaseEvent(self, event):
        if event.button() == Qt.RightButton:
            self._event_3dPoint = event
            self._menu.exec_(self._gl_view.mapToGlobal(event.pos()))

    def _set_location_action(self):
        x_cursor = self._event_3dPoint.pos().x()
        y_cursor = self._gl_view.height() - self._event_3dPoint.pos().y()

        x, y, z = self._gl_view.unproject_mouse_on_scene(QPoint(x_cursor, y_cursor))

        position_x = x / self._mapDrawer.resolution_meters
        position_y = y / self._mapDrawer.resolution_meters
        position_z = z / self._mapDrawer.resolution_meters
        self._mapDrawer.drawTarget(position_x, position_y, position_z)
        rospy.loginfo('Set Target selected at (%.2f, %.2f)', position_x, position_y)
        self.set_global_target(X=position_x, Y=position_y, Z=position_z, ROLL=0, PITCH=0, YAW=self._yaw)

    def shutdown_plugin(self):
        print 'Shutting down'
Example #41
0
class EditorWidget(QWidget):
    '''
    This class is abstract -- its child classes should be instantiated.

    There exist two kinds of "update" methods:
    - _update_paramserver for Parameter Server.
    - update_value for the value displayed on GUI.
    '''
    def __init__(self, updater, config):
        '''
        @param updater: A class that extends threading.Thread.
        @type updater: rqt_reconfigure.param_updater.ParamUpdater
        '''

        super(EditorWidget, self).__init__()

        self._updater = updater
        self.param_name = config['name']
        self.param_default = config['default']
        self.param_description = config['description']

        self.old_value = None

        self.cmenu = QMenu()
        self.cmenu.addAction(self.tr('Set to Default')).triggered.connect(
            self._set_to_default)

    def _update_paramserver(self, value):
        '''
        Update the value on Parameter Server.
        '''
        if value != self.old_value:
            self.update_configuration(value)
            self.old_value = value

    def update_value(self, value):
        '''
        To be implemented in subclass, but still used.

        Update the value that's displayed on the arbitrary GUI component
        based on user's input.

        This method is not called from the GUI thread, so any changes to
        QObjects will need to be done through a signal.
        '''
        self.old_value = value

    def update_configuration(self, value):
        self._updater.update({self.param_name: value})

    def display(self, grid):
        '''
        Should be overridden in subclass.

        :type grid: QFormLayout
        '''
        self._paramname_label.setText(self.param_name)
        #        label_paramname = QLabel(self.param_name)
        #        label_paramname.setWordWrap(True)
        self._paramname_label.setMinimumWidth(100)
        grid.addRow(self._paramname_label, self)
        self.setToolTip(self.param_description)
        self._paramname_label.setToolTip(self.param_description)
        self._paramname_label.contextMenuEvent = self.contextMenuEvent

    def close(self):
        '''
        Should be overridden in subclass.
        '''
        pass

    def _set_to_default(self):
        self._update_paramserver(self.param_default)

    def contextMenuEvent(self, e):
        self.cmenu.exec_(e.globalPos())
    def _rightclick_menu(self, event):
        """
        Dynamically builds the rightclick menu based on the unique column data
        from the passed in datamodel and then launches it modally
        :param event: the mouse event object, ''QMouseEvent''
        """
        severities = {}
        for severity, label in Message.SEVERITY_LABELS.items():
            if severity in self._model.get_unique_severities():
                severities[severity] = label
        nodes = sorted(self._model.get_unique_nodes())
        topics = sorted(self._model.get_unique_topics())

        # menutext entries turned into
        menutext = []
        menutext.append([self.tr('Exclude'), [[self.tr('Severity'), severities], [self.tr('Node'), nodes], [self.tr('Topic'), topics], [self.tr('Selected Message(s)')]]])
        menutext.append([self.tr('Highlight'), [[self.tr('Severity'), severities], [self.tr('Node'), nodes], [self.tr('Topic'), topics], [self.tr('Selected Message(s)')]]])
        menutext.append([self.tr('Copy Selected')])
        menutext.append([self.tr('Browse Selected')])

        menu = QMenu()
        submenus = []
        subsubmenus = []
        for item in menutext:
            if len(item) > 1:
                submenus.append(QMenu(item[0], menu))
                for subitem in item[1]:
                    if len(subitem) > 1:
                        subsubmenus.append(QMenu(subitem[0], submenus[-1]))
                        if isinstance(subitem[1], dict):
                            for key in sorted(subitem[1].keys()):
                                action = subsubmenus[-1].addAction(subitem[1][key])
                                action.setData(key)
                        else:
                            for subsubitem in subitem[1]:
                                subsubmenus[-1].addAction(subsubitem)
                        submenus[-1].addMenu(subsubmenus[-1])
                    else:
                        submenus[-1].addAction(subitem[0])
                menu.addMenu(submenus[-1])
            else:
                menu.addAction(item[0])
        action = menu.exec_(event.globalPos())

        if action is None or action == 0:
            return
        elif action.text() == self.tr('Browse Selected'):
            self._show_browsers()
        elif action.text() == self.tr('Copy Selected'):
            rowlist = []
            for current in self.table_view.selectionModel().selectedIndexes():
                rowlist.append(self._proxy_model.mapToSource(current).row())
            copytext = self._model.get_selected_text(rowlist)
            if copytext is not None:
                clipboard = QApplication.clipboard()
                clipboard.setText(copytext)
        elif action.text() == self.tr('Selected Message(s)'):
            if action.parentWidget().title() == self.tr('Highlight'):
                self._process_highlight_exclude_filter(action.text(), 'Message', False)
            elif action.parentWidget().title() == self.tr('Exclude'):
                self._process_highlight_exclude_filter(action.text(), 'Message', True)
            else:
                raise RuntimeError("Menu format corruption in ConsoleWidget._rightclick_menu()")
        else:
            # This processes the dynamic list entries (severity, node and topic)
            try:
                roottitle = action.parentWidget().parentWidget().title()
            except:
                raise RuntimeError("Menu format corruption in ConsoleWidget._rightclick_menu()")

            if roottitle == self.tr('Highlight'):
                self._process_highlight_exclude_filter(action.text(), action.parentWidget().title(), False)
            elif roottitle == self.tr('Exclude'):
                self._process_highlight_exclude_filter(action.text(), action.parentWidget().title(), True)
            else:
                raise RuntimeError("Unknown Root Action %s selected in ConsoleWidget._rightclick_menu()" % roottitle)
    def __init__(self, timeline, event, menu_topic):
        super(TimelinePopupMenu, self).__init__()

        self.parent = timeline
        self.timeline = timeline


        if menu_topic is not None:
            self.setTitle(menu_topic)
            self._menu_topic = menu_topic
        else:
            self._menu_topic = None

        self._reset_timeline = self.addAction('Reset Timeline')

        self._play_all = self.addAction('Play All Messages')
        self._play_all.setCheckable(True)
        self._play_all.setChecked(self.timeline.play_all)

        self.addSeparator()

        self._renderers = self.timeline._timeline_frame.get_renderers()
        self._thumbnail_actions = []

        # create thumbnail menu items
        if menu_topic is None:
            submenu = self.addMenu('Thumbnails...')
            self._thumbnail_show_action = submenu.addAction('Show All')
            self._thumbnail_hide_action = submenu.addAction('Hide All')
            submenu.addSeparator()

            for topic, renderer in self._renderers:
                self._thumbnail_actions.append(submenu.addAction(topic))
                self._thumbnail_actions[-1].setCheckable(True)
                self._thumbnail_actions[-1].setChecked(self.timeline._timeline_frame.is_renderer_active(topic))
        else:
            self._thumbnail_show_action = None
            self._thumbnail_hide_action = None
            for topic, renderer in self._renderers:
                if menu_topic == topic:
                    self._thumbnail_actions.append(self.addAction("Thumbnail"))
                    self._thumbnail_actions[-1].setCheckable(True)
                    self._thumbnail_actions[-1].setChecked(self.timeline._timeline_frame.is_renderer_active(topic))

        # create view menu items
        self._topic_actions = []
        self._type_actions = []
        if menu_topic is None:
            self._topics = self.timeline._timeline_frame.topics
            view_topics_menu = self.addMenu('View (by Topic)')
            for topic in self._topics:
                datatype = self.timeline.get_datatype(topic)

                # View... / topic
                topic_menu = QMenu(topic, self)
                viewer_types = self.timeline._timeline_frame.get_viewer_types(datatype)

                # View... / topic / Viewer
                for viewer_type in viewer_types:
                    tempaction = topic_menu.addAction(viewer_type.name)
                    tempaction.setData(viewer_type)
                    self._topic_actions.append(tempaction)
                view_topics_menu.addMenu(topic_menu)

            view_type_menu = self.addMenu('View (by Type)')
            self._topics_by_type = self.timeline._timeline_frame._topics_by_datatype
            for datatype in self._topics_by_type:
                # View... / datatype
                datatype_menu = QMenu(datatype, self)
                datatype_topics = self._topics_by_type[datatype]
                viewer_types = self.timeline._timeline_frame.get_viewer_types(datatype)
                for topic in [t for t in self._topics if t in datatype_topics]:   # use timeline ordering
                    topic_menu = QMenu(topic, datatype_menu)
                    # View... / datatype / topic / Viewer
                    for viewer_type in viewer_types:
                        tempaction = topic_menu.addAction(viewer_type.name)
                        tempaction.setData(viewer_type)
                        self._topic_actions.append(tempaction)
                    datatype_menu.addMenu(topic_menu)
                view_type_menu.addMenu(datatype_menu)
        else:
            view_menu = self.addMenu("View")
            datatype = self.timeline.get_datatype(menu_topic)

            viewer_types = self.timeline._timeline_frame.get_viewer_types(datatype)
            for viewer_type in viewer_types:
                tempaction = view_menu.addAction(viewer_type.name)
                tempaction.setData(viewer_type)
                self._topic_actions.append(tempaction)

        self.addSeparator()

        # create publish menu items
        self._publish_actions = []
        if menu_topic is None:
            submenu = self.addMenu('Publish...')

            self._publish_all = submenu.addAction('Publish All')
            self._publish_none = submenu.addAction('Publish None')

            submenu.addSeparator()

            for topic in self._topics:
                self._publish_actions.append(submenu.addAction(topic))
                self._publish_actions[-1].setCheckable(True)
                self._publish_actions[-1].setChecked(self.timeline.is_publishing(topic))
        else:
            self._publish_actions.append(self.addAction("Publish"))
            self._publish_actions[-1].setCheckable(True)
            self._publish_actions[-1].setChecked(self.timeline.is_publishing(menu_topic))
            self._publish_all = None
            self._publish_none = None



        action = self.exec_(event.globalPos())
        if action is not None and action != 0:
            self.process(action)
Example #44
0
    def _rightclick_menu(self, event):
        """
        Dynamically builds the rightclick menu based on the unique column data
        from the passed in datamodel and then launches it modally
        :param event: the mouse event object, ''QMouseEvent''
        """
        severities = {}
        for severity, label in Message.SEVERITY_LABELS.items():
            if severity in self._model.get_unique_severities():
                severities[severity] = label
        nodes = sorted(self._model.get_unique_nodes())
        topics = sorted(self._model.get_unique_topics())

        # menutext entries turned into
        menutext = []
        menutext.append([
            self.tr('Exclude'),
            [[self.tr('Severity'), severities], [self.tr('Node'), nodes],
             [self.tr('Topic'), topics], [self.tr('Selected Message(s)')]]
        ])
        menutext.append([
            self.tr('Highlight'),
            [[self.tr('Severity'), severities], [self.tr('Node'), nodes],
             [self.tr('Topic'), topics], [self.tr('Selected Message(s)')]]
        ])
        menutext.append([self.tr('Copy Selected')])
        menutext.append([self.tr('Browse Selected')])

        menu = QMenu()
        submenus = []
        subsubmenus = []
        for item in menutext:
            if len(item) > 1:
                submenus.append(QMenu(item[0], menu))
                for subitem in item[1]:
                    if len(subitem) > 1:
                        subsubmenus.append(QMenu(subitem[0], submenus[-1]))
                        if isinstance(subitem[1], dict):
                            for key in sorted(subitem[1].keys()):
                                action = subsubmenus[-1].addAction(
                                    subitem[1][key])
                                action.setData(key)
                        else:
                            for subsubitem in subitem[1]:
                                subsubmenus[-1].addAction(subsubitem)
                        submenus[-1].addMenu(subsubmenus[-1])
                    else:
                        submenus[-1].addAction(subitem[0])
                menu.addMenu(submenus[-1])
            else:
                menu.addAction(item[0])
        action = menu.exec_(event.globalPos())

        if action is None or action == 0:
            return
        elif action.text() == self.tr('Browse Selected'):
            self._show_browsers()
        elif action.text() == self.tr('Copy Selected'):
            rowlist = []
            for current in self.table_view.selectionModel().selectedIndexes():
                rowlist.append(self._proxy_model.mapToSource(current).row())
            copytext = self._model.get_selected_text(rowlist)
            if copytext is not None:
                clipboard = QApplication.clipboard()
                clipboard.setText(copytext)
        elif action.text() == self.tr('Selected Message(s)'):
            if action.parentWidget().title() == self.tr('Highlight'):
                self._process_highlight_exclude_filter(action.text(),
                                                       'Message', False)
            elif action.parentWidget().title() == self.tr('Exclude'):
                self._process_highlight_exclude_filter(action.text(),
                                                       'Message', True)
            else:
                raise RuntimeError(
                    "Menu format corruption in ConsoleWidget._rightclick_menu()"
                )
        else:
            # This processes the dynamic list entries (severity, node and topic)
            try:
                roottitle = action.parentWidget().parentWidget().title()
            except:
                raise RuntimeError(
                    "Menu format corruption in ConsoleWidget._rightclick_menu()"
                )

            if roottitle == self.tr('Highlight'):
                self._process_highlight_exclude_filter(
                    action.text(),
                    action.parentWidget().title(), False)
            elif roottitle == self.tr('Exclude'):
                self._process_highlight_exclude_filter(
                    action.text(),
                    action.parentWidget().title(), True)
            else:
                raise RuntimeError(
                    "Unknown Root Action %s selected in ConsoleWidget._rightclick_menu()"
                    % roottitle)
Example #45
0
class PlotWidget(QWidget):
    _redraw_interval = 40

    def __init__(self, node, initial_topics=None, start_paused=False):
        super(PlotWidget, self).__init__()
        self.setObjectName('PlotWidget')

        self._node = node
        self._initial_topics = initial_topics

        _, package_path = get_resource('packages', 'rqt_plot')
        ui_file = os.path.join(package_path, 'share', '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(node)
        self.topic_edit.setCompleter(self._topic_completer)

        self._start_time = time.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 switch_data_plot_widget(self, data_plot):
        self.enable_timer(enabled=False)

        self.data_plot_layout.removeWidget(self.data_plot)
        if self.data_plot is not None:
            self.data_plot.close()

        self.data_plot = data_plot
        self.data_plot_layout.addWidget(self.data_plot)
        self.data_plot.autoscroll(self.autoscroll_checkbox.isChecked())

        # setup drag 'n drop
        self.data_plot.dropEvent = self.dropEvent
        self.data_plot.dragEnterEvent = self.dragEnterEvent

        if self._initial_topics:
            for topic_name in self._initial_topics:
                self.add_topic(topic_name)
            self._initial_topics = None
        else:
            for topic_name, rosdata in self._rosdata.items():
                data_x, data_y = rosdata.next()
                self.data_plot.add_curve(topic_name, topic_name, data_x,
                                         data_y)

        self._subscribed_topics_changed()

    @Slot('QDragEnterEvent*')
    def dragEnterEvent(self, event):
        # get topic name
        if not event.mimeData().hasText():
            if not hasattr(event.source(), 'selectedItems') or \
                    len(event.source().selectedItems()) == 0:
                qWarning(
                    'Plot.dragEnterEvent(): not hasattr(event.source(), selectedItems) or '
                    'len(event.source().selectedItems()) == 0')
                return
            item = event.source().selectedItems()[0]
            topic_name = item.data(0, Qt.UserRole)
            if topic_name == None:
                qWarning(
                    'Plot.dragEnterEvent(): not hasattr(item, ros_topic_name_)'
                )
                return
        else:
            topic_name = str(event.mimeData().text())

        # check for plottable field type
        plottable, message = is_plottable(self._node, topic_name)
        if plottable:
            event.acceptProposedAction()
        else:
            qWarning('Plot.dragEnterEvent(): rejecting: "%s"' % (message))

    @Slot('QDropEvent*')
    def dropEvent(self, event):
        if event.mimeData().hasText():
            topic_name = str(event.mimeData().text())
        else:
            droped_item = event.source().selectedItems()[0]
            topic_name = str(droped_item.data(0, Qt.UserRole))
        self.add_topic(topic_name)

    @Slot(str)
    def on_topic_edit_textChanged(self, topic_name):
        # on empty topic name, update topics
        if topic_name in ('', '/'):
            self._topic_completer.update_topics(self._node)

        plottable, message = is_plottable(self._node, topic_name)
        self.subscribe_topic_button.setEnabled(plottable)
        self.subscribe_topic_button.setToolTip(message)

    @Slot()
    def on_topic_edit_returnPressed(self):
        if self.subscribe_topic_button.isEnabled():
            self.add_topic(str(self.topic_edit.text()))

    @Slot()
    def on_subscribe_topic_button_clicked(self):
        self.add_topic(str(self.topic_edit.text()))

    @Slot(bool)
    def on_pause_button_clicked(self, checked):
        self.enable_timer(not checked)

    @Slot(bool)
    def on_autoscroll_checkbox_clicked(self, checked):
        self.data_plot.autoscroll(checked)
        if checked:
            self.data_plot.redraw()

    @Slot()
    def on_clear_button_clicked(self):
        self.clear_plot()

    def update_plot(self):
        if self.data_plot is not None:
            needs_redraw = False
            for topic_name, rosdata in self._rosdata.items():
                try:
                    data_x, data_y = rosdata.next()
                    if data_x or data_y:
                        self.data_plot.update_values(topic_name, data_x,
                                                     data_y)
                        needs_redraw = True
                except RosPlotException as e:
                    qWarning('PlotWidget.update_plot(): error in rosplot: %s' %
                             e)
            if needs_redraw:
                self.data_plot.redraw()

    def _subscribed_topics_changed(self):
        self._update_remove_topic_menu()
        if not self.pause_button.isChecked():
            # if pause button is not pressed, enable timer based on subscribed topics
            self.enable_timer(self._rosdata)
        self.data_plot.redraw()

    def _update_remove_topic_menu(self):
        def make_remove_topic_function(x):
            return lambda: self.remove_topic(x)

        self._remove_topic_menu.clear()
        for topic_name in sorted(self._rosdata.keys()):
            action = QAction(topic_name, self._remove_topic_menu)
            action.triggered.connect(make_remove_topic_function(topic_name))
            self._remove_topic_menu.addAction(action)

        if len(self._rosdata) > 1:
            all_action = QAction('All', self._remove_topic_menu)
            all_action.triggered.connect(self.clean_up_subscribers)
            self._remove_topic_menu.addAction(all_action)

        self.remove_topic_button.setMenu(self._remove_topic_menu)

    def add_topic(self, topic_name):
        topics_changed = False
        for topic_name in get_plot_fields(self._node, topic_name)[0]:
            if topic_name in self._rosdata:
                qWarning(
                    'PlotWidget.add_topic(): topic already subscribed: %s' %
                    topic_name)
                continue
            self._rosdata[topic_name] = ROSData(self._node, topic_name,
                                                self._start_time)
            if self._rosdata[topic_name].error is not None:
                qWarning(str(self._rosdata[topic_name].error))
                del self._rosdata[topic_name]
            else:
                data_x, data_y = self._rosdata[topic_name].next()
                self.data_plot.add_curve(topic_name, topic_name, data_x,
                                         data_y)
                topics_changed = True

        if topics_changed:
            self._subscribed_topics_changed()

    def remove_topic(self, topic_name):
        self._rosdata[topic_name].close()
        del self._rosdata[topic_name]
        self.data_plot.remove_curve(topic_name)

        self._subscribed_topics_changed()

    def clear_plot(self):
        for topic_name, _ in self._rosdata.items():
            self.data_plot.clear_values(topic_name)
        self.data_plot.redraw()

    def clean_up_subscribers(self):
        for topic_name, rosdata in self._rosdata.items():
            rosdata.close()
            self.data_plot.remove_curve(topic_name)
        self._rosdata = {}

        self._subscribed_topics_changed()

    def enable_timer(self, enabled=True):
        if enabled:
            self._update_plot_timer.start(self._redraw_interval)
        else:
            self._update_plot_timer.stop()
Example #46
0
class PlotWidget(QWidget):
    _redraw_interval = 40

    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 switch_data_plot_widget(self, data_plot):
        self.enable_timer(enabled=False)

        self.data_plot_layout.removeWidget(self.data_plot)
        if self.data_plot is not None:
            self.data_plot.close()

        self.data_plot = data_plot
        self.data_plot_layout.addWidget(self.data_plot)
        self.data_plot.autoscroll(self.autoscroll_checkbox.isChecked())

        # setup drag 'n drop
        self.data_plot.dropEvent = self.dropEvent
        self.data_plot.dragEnterEvent = self.dragEnterEvent

        if self._initial_topics:
            for topic_name in self._initial_topics:
                self.add_topic(topic_name)
            self._initial_topics = None
        else:
            for topic_name, rosdata in self._rosdata.items():
                data_x, data_y = rosdata.next()
                self.data_plot.add_curve(topic_name, topic_name, data_x, data_y)

        self._subscribed_topics_changed()

    @Slot('QDragEnterEvent*')
    def dragEnterEvent(self, event):
        # get topic name
        if not event.mimeData().hasText():
            if not hasattr(event.source(), 'selectedItems') or len(event.source().selectedItems()) == 0:
                qWarning('Plot.dragEnterEvent(): not hasattr(event.source(), selectedItems) or len(event.source().selectedItems()) == 0')
                return
            item = event.source().selectedItems()[0]
            topic_name = item.data(0, Qt.UserRole)
            if topic_name == None:
                qWarning('Plot.dragEnterEvent(): not hasattr(item, ros_topic_name_)')
                return
        else:
            topic_name = str(event.mimeData().text())

        # check for plottable field type
        plottable, message = is_plottable(topic_name)
        if plottable:
            event.acceptProposedAction()
        else:
            qWarning('Plot.dragEnterEvent(): rejecting: "%s"' % (message))

    @Slot('QDropEvent*')
    def dropEvent(self, event):
        if event.mimeData().hasText():
            topic_name = str(event.mimeData().text())
        else:
            droped_item = event.source().selectedItems()[0]
            topic_name = str(droped_item.data(0, Qt.UserRole))
        self.add_topic(topic_name)

    @Slot(str)
    def on_topic_edit_textChanged(self, topic_name):
        # on empty topic name, update topics
        if topic_name in ('', '/'):
            self._topic_completer.update_topics()

        plottable, message = is_plottable(topic_name)
        self.subscribe_topic_button.setEnabled(plottable)
        self.subscribe_topic_button.setToolTip(message)

    @Slot()
    def on_topic_edit_returnPressed(self):
        if self.subscribe_topic_button.isEnabled():
            self.add_topic(str(self.topic_edit.text()))

    @Slot()
    def on_subscribe_topic_button_clicked(self):
        self.add_topic(str(self.topic_edit.text()))

    @Slot(bool)
    def on_pause_button_clicked(self, checked):
        self.enable_timer(not checked)

    @Slot(bool)
    def on_autoscroll_checkbox_clicked(self, checked):
        self.data_plot.autoscroll(checked)
        if checked:
            self.data_plot.redraw()

    @Slot()
    def on_clear_button_clicked(self):
        self.clear_plot()

    def update_plot(self):
        if self.data_plot is not None:
            needs_redraw = False
            for topic_name, rosdata in self._rosdata.items():
                try:
                    data_x, data_y = rosdata.next()
                    if data_x or data_y:
                        self.data_plot.update_values(topic_name, data_x, data_y)
                        needs_redraw = True
                except RosPlotException as e:
                    qWarning('PlotWidget.update_plot(): error in rosplot: %s' % e)
            if needs_redraw:
                self.data_plot.redraw()

    def _subscribed_topics_changed(self):
        self._update_remove_topic_menu()
        if not self.pause_button.isChecked():
            # if pause button is not pressed, enable timer based on subscribed topics
            self.enable_timer(self._rosdata)
        self.data_plot.redraw()

    def _update_remove_topic_menu(self):
        def make_remove_topic_function(x):
            return lambda: self.remove_topic(x)

        self._remove_topic_menu.clear()
        for topic_name in sorted(self._rosdata.keys()):
            action = QAction(topic_name, self._remove_topic_menu)
            action.triggered.connect(make_remove_topic_function(topic_name))
            self._remove_topic_menu.addAction(action)

        if len(self._rosdata) > 1:
            all_action = QAction('All', self._remove_topic_menu)
            all_action.triggered.connect(self.clean_up_subscribers)
            self._remove_topic_menu.addAction(all_action)

        self.remove_topic_button.setMenu(self._remove_topic_menu)

    def add_topic(self, topic_name):
        topics_changed = False
        for topic_name in get_plot_fields(topic_name)[0]:
            if topic_name in self._rosdata:
                qWarning('PlotWidget.add_topic(): topic already subscribed: %s' % topic_name)
                continue
            self._rosdata[topic_name] = ROSData(topic_name, self._start_time)
            if self._rosdata[topic_name].error is not None:
                qWarning(str(self._rosdata[topic_name].error))
                del self._rosdata[topic_name]
            else:
                data_x, data_y = self._rosdata[topic_name].next()
                self.data_plot.add_curve(topic_name, topic_name, data_x, data_y)
                topics_changed = True

        if topics_changed:
            self._subscribed_topics_changed()

    def remove_topic(self, topic_name):
        self._rosdata[topic_name].close()
        del self._rosdata[topic_name]
        self.data_plot.remove_curve(topic_name)

        self._subscribed_topics_changed()

    def clear_plot(self):
        for topic_name, _ in self._rosdata.items():
            self.data_plot.clear_values(topic_name)
        self.data_plot.redraw()

    def clean_up_subscribers(self):
        for topic_name, rosdata in self._rosdata.items():
            rosdata.close()
            self.data_plot.remove_curve(topic_name)
        self._rosdata = {}

        self._subscribed_topics_changed()

    def enable_timer(self, enabled=True):
        if enabled:
            self._update_plot_timer.start(self._redraw_interval)
        else:
            self._update_plot_timer.stop()
Example #47
0
class Plot3DWidget(QWidget):
    _redraw_interval = 40

    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

    @Slot('QDragEnterEvent*')
    def dragEnterEvent(self, event):
        # get topic name
        if not event.mimeData().hasText():
            if not hasattr(event.source(), 'selectedItems') or \
               len(event.source().selectedItems()) == 0:
                qWarning(
                    'Plot.dragEnterEvent(): not hasattr(event.source(), selectedItems) or len(event.source().selectedItems()) == 0'
                )  # NOQA
                return
            item = event.source().selectedItems()[0]
            topic_name = item.data(0, Qt.UserRole)
            if topic_name == None:
                qWarning(
                    'Plot.dragEnterEvent(): not hasattr(item, ros_topic_name_)'
                )  # NOQA
                return
        else:
            topic_name = str(event.mimeData().text())

        # check for numeric field type
        is_numeric, is_array, message = is_slot_numeric(topic_name)
        if is_numeric and not is_array:
            event.acceptProposedAction()
        else:
            qWarning('Plot.dragEnterEvent(): rejecting: "%s"' % (message))

    @Slot('QDropEvent*')
    def dropEvent(self, event):
        if event.mimeData().hasText():
            topic_name = str(event.mimeData().text())
        else:
            droped_item = event.source().selectedItems()[0]
            topic_name = str(droped_item.data(0, Qt.UserRole))
        self.add_topic(topic_name)

    @Slot(str)
    def on_topic_edit_textChanged(self, topic_name):
        # on empty topic name, update topics
        if topic_name in ('', '/'):
            self._topic_completer.update_topics()

        is_numeric, is_array, message = is_slot_numeric(topic_name)
        self.subscribe_topic_button.setEnabled(is_numeric and not is_array)
        self.subscribe_topic_button.setToolTip(message)

    @Slot()
    def on_topic_edit_returnPressed(self):
        if self.subscribe_topic_button.isEnabled():
            self.add_topic(str(self.topic_edit.text()))

    @Slot()
    def on_subscribe_topic_button_clicked(self):
        self.add_topic(str(self.topic_edit.text()))

    @Slot(bool)
    def on_pause_button_clicked(self, checked):
        self.enable_timer(not checked)

    @Slot(bool)
    def on_autoscroll_checkbox_clicked(self, checked):
        self.data_plot.autoscroll(checked)

    @Slot()
    def on_clear_button_clicked(self):
        self.clean_up_subscribers()

    def update_plot(self):
        if self.data_plot is not None:
            needs_redraw = False
            for topic_name, rosdata in self._rosdata.items():
                try:
                    data_x, data_y = rosdata.next()
                    if data_x or data_y:
                        self.data_plot.update_values(topic_name, data_x,
                                                     data_y)
                        needs_redraw = True
                except RosPlotException as e:
                    qWarning('PlotWidget.update_plot(): error in rosplot: %s' %
                             e)
            if needs_redraw:
                self.data_plot.redraw()

    def _subscribed_topics_changed(self):
        self._update_remove_topic_menu()
        if not self.pause_button.isChecked():
            # if pause button is not pressed,
            # enable timer based on subscribed topics
            self.enable_timer(self._rosdata)

    def _update_remove_topic_menu(self):
        def make_remove_topic_function(x):
            return lambda: self.remove_topic(x)

        self._remove_topic_menu.clear()
        for topic_name in sorted(self._rosdata.keys()):
            action = QAction(topic_name, self._remove_topic_menu)
            action.triggered.connect(make_remove_topic_function(topic_name))
            self._remove_topic_menu.addAction(action)

        self.remove_topic_button.setMenu(self._remove_topic_menu)

    def add_topic(self, topic_name):
        if topic_name in self._rosdata:
            qWarning('PlotWidget.add_topic(): topic already subscribed: %s' %
                     topic_name)  # NOQA
            return

        self._rosdata[topic_name] = ROSData(topic_name, self._start_time)
        if self._rosdata[topic_name].error is not None:
            qWarning(str(self._rosdata[topic_name].error))
            del self._rosdata[topic_name]
        else:
            data_x, data_y = self._rosdata[topic_name].next()
            self.data_plot.add_curve(topic_name, topic_name, data_x, data_y)

            self._subscribed_topics_changed()

    def remove_topic(self, topic_name):
        self._rosdata[topic_name].close()
        del self._rosdata[topic_name]
        self.data_plot.remove_curve(topic_name)

        self._subscribed_topics_changed()

    def clean_up_subscribers(self):
        for topic_name, rosdata in self._rosdata.items():
            rosdata.close()
            self.data_plot.remove_curve(topic_name)
        self._rosdata = {}

        self._subscribed_topics_changed()

    def enable_timer(self, enabled=True):
        if enabled:
            self._update_plot_timer.start(self._redraw_interval)
        else:
            self._update_plot_timer.stop()
Example #48
0
    def __init__(self, timeline, event, menu_topic):
        super(TimelinePopupMenu, self).__init__()

        self.parent = timeline
        self.timeline = timeline

        if menu_topic is not None:
            self.setTitle(menu_topic)
            self._menu_topic = menu_topic
        else:
            self._menu_topic = None

        self._reset_timeline = self.addAction('Reset Timeline')

        self._play_all = self.addAction('Play All Messages')
        self._play_all.setCheckable(True)
        self._play_all.setChecked(self.timeline.play_all)

        self.addSeparator()

        self._renderers = self.timeline._timeline_frame.get_renderers()
        self._thumbnail_actions = []

        # create thumbnail menu items
        if menu_topic is None:
            submenu = self.addMenu('Thumbnails...')
            self._thumbnail_show_action = submenu.addAction('Show All')
            self._thumbnail_hide_action = submenu.addAction('Hide All')
            submenu.addSeparator()

            for topic, renderer in self._renderers:
                self._thumbnail_actions.append(submenu.addAction(topic))
                self._thumbnail_actions[-1].setCheckable(True)
                self._thumbnail_actions[-1].setChecked(
                    self.timeline._timeline_frame.is_renderer_active(topic))
        else:
            self._thumbnail_show_action = None
            self._thumbnail_hide_action = None
            for topic, renderer in self._renderers:
                if menu_topic == topic:
                    self._thumbnail_actions.append(self.addAction("Thumbnail"))
                    self._thumbnail_actions[-1].setCheckable(True)
                    self._thumbnail_actions[-1].setChecked(
                        self.timeline._timeline_frame.is_renderer_active(
                            topic))

        # create view menu items
        self._topic_actions = []
        self._type_actions = []
        if menu_topic is None:
            self._topics = self.timeline._timeline_frame.topics
            view_topics_menu = self.addMenu('View (by Topic)')
            for topic in self._topics:
                datatype = self.timeline.get_datatype(topic)

                # View... / topic
                topic_menu = QMenu(topic, self)
                viewer_types = self.timeline._timeline_frame.get_viewer_types(
                    datatype)

                # View... / topic / Viewer
                for viewer_type in viewer_types:
                    tempaction = topic_menu.addAction(viewer_type.name)
                    tempaction.setData(viewer_type)
                    self._topic_actions.append(tempaction)
                view_topics_menu.addMenu(topic_menu)

            view_type_menu = self.addMenu('View (by Type)')
            self._topics_by_type = self.timeline._timeline_frame._topics_by_datatype
            for datatype in self._topics_by_type:
                # View... / datatype
                datatype_menu = QMenu(datatype, self)
                datatype_topics = self._topics_by_type[datatype]
                viewer_types = self.timeline._timeline_frame.get_viewer_types(
                    datatype)
                for topic in [t for t in self._topics if t in datatype_topics
                              ]:  # use timeline ordering
                    topic_menu = QMenu(topic, datatype_menu)
                    # View... / datatype / topic / Viewer
                    for viewer_type in viewer_types:
                        tempaction = topic_menu.addAction(viewer_type.name)
                        tempaction.setData(viewer_type)
                        self._topic_actions.append(tempaction)
                    datatype_menu.addMenu(topic_menu)
                view_type_menu.addMenu(datatype_menu)
        else:
            view_menu = self.addMenu("View")
            datatype = self.timeline.get_datatype(menu_topic)

            viewer_types = self.timeline._timeline_frame.get_viewer_types(
                datatype)
            for viewer_type in viewer_types:
                tempaction = view_menu.addAction(viewer_type.name)
                tempaction.setData(viewer_type)
                self._topic_actions.append(tempaction)

        self.addSeparator()

        # create publish menu items
        self._publish_actions = []
        if menu_topic is None:
            submenu = self.addMenu('Publish...')

            self._publish_all = submenu.addAction('Publish All')
            self._publish_none = submenu.addAction('Publish None')

            submenu.addSeparator()

            for topic in self._topics:
                self._publish_actions.append(submenu.addAction(topic))
                self._publish_actions[-1].setCheckable(True)
                self._publish_actions[-1].setChecked(
                    self.timeline.is_publishing(topic))
        else:
            self._publish_actions.append(self.addAction("Publish"))
            self._publish_actions[-1].setCheckable(True)
            self._publish_actions[-1].setChecked(
                self.timeline.is_publishing(menu_topic))
            self._publish_all = None
            self._publish_none = None

        action = self.exec_(event.globalPos())
        if action is not None and action != 0:
            self.process(action)
class EditorWidget(QWidget):
    '''
    This class is abstract -- its child classes should be instantiated.

    There exist two kinds of "update" methods:
    - _update_paramserver for Parameter Server.
    - update_value for the value displayed on GUI.
    '''

    def __init__(self, updater, config):
        '''
        @param updater: A class that extends threading.Thread.
        @type updater: rqt_reconfigure.param_updater.ParamUpdater
        '''

        super(EditorWidget, self).__init__()

        self._updater = updater
        self.param_name = config['name']
        self.param_default = config['default']
        self.param_description = config['description']

        self.old_value = None

        self.cmenu = QMenu()
        self.cmenu.addAction(self.tr('Set to Default')).triggered.connect(self._set_to_default)

    def _update_paramserver(self, value):
        '''
        Update the value on Parameter Server.
        '''
        if value != self.old_value:
            self.update_configuration(value)
            self.old_value = value

    def update_value(self, value):
        '''
        To be implemented in subclass, but still used.

        Update the value that's displayed on the arbitrary GUI component
        based on user's input.

        This method is not called from the GUI thread, so any changes to
        QObjects will need to be done through a signal.
        '''
        self.old_value = value

    def update_configuration(self, value):
        self._updater.update({self.param_name: value})

    def display(self, grid):
        '''
        Should be overridden in subclass.

        :type grid: QFormLayout
        '''
        self._paramname_label.setText(self.param_name)
#        label_paramname = QLabel(self.param_name)
#        label_paramname.setWordWrap(True)
        self._paramname_label.setMinimumWidth(100)
        grid.addRow(self._paramname_label, self)
        self.setToolTip(self.param_description)
        self._paramname_label.setToolTip(self.param_description)
        self._paramname_label.contextMenuEvent = self.contextMenuEvent

    def close(self):
        '''
        Should be overridden in subclass.
        '''
        pass

    def _set_to_default(self):
        self._update_paramserver(self.param_default)

    def contextMenuEvent(self, e):
        self.cmenu.exec_(e.globalPos())
 def handle_customContextMenuRequested(self, pos):
     # show context menu
     menu = QMenu(self)
     self._context_menu_add_actions(menu, pos)
     menu.exec_(self.mapToGlobal(pos))
class PlotWidget(QWidget):
    _redraw_interval = 40

    def __init__(self, initial_topics=None, start_paused=False):
        super(PlotWidget, self).__init__()
        self.setObjectName('PlotWidget')

        # Available ros topics for plotting
        # keys are i=InitSub, s=StateSub, r=RCSub, p=PathSub, w=WaypointSub,
        #          o=ObstacleSub, g=GPSDataSub, ci=ConInSub, cc=ConComSub
        self.message_dict = {
            'Course angle vs. Commanded': [('cc', 'chi_c'), ('s', 'chi')],
            'Roll angle vs. Commanded': [('ci', 'phi_c'), ('s', 'phi')],
            'Pitch angle vs. Commanded': [('s', 'theta'), ('ci', 'theta_c')],
            'Airspeed vs. Commanded': [('s', 'Va'), ('cc', 'Va_c')]
        }

        # # Available ros topics for plotting
        # self.message_dict = {
        #     'Course angle (rad)':'/state/chi',
        #     'Course angle commanded (rad)':'/controller_commands/chi_c',
        #     'Airspeed (m/s)':'/state/Va',
        #     'Angle of attack (rad)':'/state/alpha',
        #     'Slide slip angle (rad)':'/state/beta',
        #     'Roll angle (rad)':'/state/phi',
        #     'Pitch angle (rad)':'/state/theta',
        #     'Yaw angle (rad)':'/state/psi',
        #     'Body frame rollrate (rad/s)':'/state/p',
        #     'Body frame pitchrate (rad/s)':'/state/q',
        #     'Body frame yawrate (rad/s)':'/state/r',
        #     'Groundspeed (m/s)':'/state/Vg'
        #     }

        #self._initial_topics = initial_topics

        rp = rospkg.RosPack()
        ui_file = os.path.join(PWD, 'resources', 'plot.ui')
        loadUi(ui_file, self)

        self.pause_button.setIcon(QIcon.fromTheme('media-playback-pause'))
        self.clear_button.setIcon(QIcon.fromTheme('edit-clear'))
        self.data_plot = None

        if start_paused:
            self.pause_button.setChecked(True)

        self._start_time = rospy.get_time()
        self._rosdata = {}

        self._current_key = ''
        self._current_topics = []

        self._remove_topic_menu = QMenu()

        self._msgs.clear()
        self._msgs.addItems(self.message_dict.keys())

        self._msgs.currentIndexChanged[str].connect(
            self._draw_graph)  # <<<<<<< start here (also modify the dict)

        # init and start update timer for plot
        self._update_plot_timer = QTimer(self)
        self._update_plot_timer.timeout.connect(self.update_plot)

    def switch_data_plot_widget(self, data_plot):
        self.enable_timer(enabled=False)

        self.data_plot_layout.removeWidget(self.data_plot)
        if self.data_plot is not None:
            self.data_plot.close()

        self.data_plot = data_plot
        self.data_plot_layout.addWidget(self.data_plot)
        self.data_plot.autoscroll(True)

        # setup drag 'n drop
        self.data_plot.dropEvent = self.dropEvent
        self.data_plot.dragEnterEvent = self.dragEnterEvent
        '''
        if self._initial_topics:
            for topic_name in self._initial_topics:
                self.add_topic(topic_name)
            self._initial_topics = None
        else:
            for topic_name, rosdata in self._rosdata.items():
                data_x, data_y = rosdata.next()
                self.data_plot.add_curve(topic_name, topic_name, data_x, data_y)

        self._subscribed_topics_changed()
        '''

    def _draw_graph(self):
        #print 'entering _draw_graph'
        # NOT GONNA WORRY ABOUT THIS!
        # plottable, message = is_plottable(self.message_dict[self._msgs.currentText()]) # <<<<<< will feed this a list

        if self._current_key and not (self._msgs.currentText()
                                      == self._current_key):
            for topic_tuple in self._current_topics:
                #print 'removing %s from plot' % topic # ------------------------
                self.remove_topic(topic_tuple[0], topic_tuple[1])
            self._current_topics = []

        self._current_topics = []

        self._current_key = self._msgs.currentText()
        #print 'current key:', self._current_key
        for topic_tuple in self.message_dict[self._current_key]:
            #topic = get_topic(topic_tuple)
            #print 'topic:', topic
            #if not (topic is None):
            self._current_topics.append(topic_tuple)
            #print 'adding %s to plot' % topic # --------------------------
            self.add_topic(topic_tuple[0], topic_tuple[1])
        self._subscribed_topics_changed()

    @Slot(bool)
    def on_pause_button_clicked(self, checked):
        self.enable_timer(not checked)

    @Slot()
    def on_clear_button_clicked(self):
        self.clear_plot()

    def update_plot(self):
        if self.data_plot is not None:
            needs_redraw = False
            for topic_name, rosdata in self._rosdata.items():
                try:
                    data_x, data_y = rosdata.next()
                    if data_x or data_y:
                        self.data_plot.update_values(topic_name, data_x,
                                                     data_y)
                        needs_redraw = True
                except RosPlotException as e:
                    qWarning('PlotWidget.update_plot(): error in rosplot: %s' %
                             e)
            if needs_redraw:
                self.data_plot.redraw()

    def _subscribed_topics_changed(self):
        #self._update_remove_topic_menu() # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
        if not self.pause_button.isChecked():
            # if pause button is not pressed, enable timer based on subscribed topics
            self.enable_timer(self._rosdata)
        self.data_plot.redraw()

    def _update_remove_topic_menu(self):
        def make_remove_topic_function(x):
            return lambda: self.remove_topic(x)

        self._remove_topic_menu.clear()
        for topic_name in sorted(self._rosdata.keys()):
            action = QAction(topic_name, self._remove_topic_menu)
            action.triggered.connect(make_remove_topic_function(topic_name))
            self._remove_topic_menu.addAction(action)

        if len(self._rosdata) > 1:
            all_action = QAction('All', self._remove_topic_menu)
            all_action.triggered.connect(self.clean_up_subscribers)
            self._remove_topic_menu.addAction(all_action)

    def add_topic(self, topic_code, topic_item):
        topics_changed = False
        topic_name = topic_code + '/' + topic_item
        #for topic_name in get_plot_fields(topic_name)[0]: # <<<<<<<< this is what allows for multiple topics
        if topic_name in self._rosdata:
            qWarning('PlotWidget.add_topic(): topic already subscribed: %s' %
                     topic_name)
            #continue
            return

        self._rosdata[topic_name] = ROSData(topic_code, topic_item,
                                            self._start_time)

        if self._rosdata[topic_name].error is not None:
            qWarning(str(self._rosdata[topic_name].error))
            del self._rosdata[topic_name]
        else:
            data_x, data_y = self._rosdata[topic_name].next()
            self.data_plot.add_curve(topic_name, topic_name, data_x, data_y)
            #print self._rosdata.items() # ------------------------------------------
            topics_changed = True

        #if topics_changed:
        #    self._subscribed_topics_changed()

    def remove_topic(self, topic_code, topic_item):
        topic_name = topic_code + '/' + topic_item
        self._rosdata[topic_name].close()
        del self._rosdata[topic_name]
        self.data_plot.remove_curve(topic_name)

        self._subscribed_topics_changed()

    def clear_plot(self):
        for topic_name, _ in self._rosdata.items():
            self.data_plot.clear_values(topic_name)
        self.data_plot.redraw()

    def clean_up_subscribers(self):
        for topic_name, rosdata in self._rosdata.items():
            rosdata.close()
            self.data_plot.remove_curve(topic_name)
        self._rosdata = {}

        self._subscribed_topics_changed()

    def enable_timer(self, enabled=True):
        if enabled:
            self._update_plot_timer.start(self._redraw_interval)
        else:
            self._update_plot_timer.stop()