Exemple #1
0
    def _update_client_tab(self):
        print('[conductor graph]: _update_client_tab')
        self.pre_selected_client_name = self.cur_selected_client_name
        self._widget.tabWidget.clear()

        for k in self._graph.concert_clients.values():
            # Only pull in information from connected or connectable clients
            if k.state not in [
                    concert_msgs.ConcertClientState.AVAILABLE,
                    concert_msgs.ConcertClientState.MISSING,
                    concert_msgs.ConcertClientState.UNINVITED
            ]:
                continue

            main_widget = QWidget()

            ver_layout = QVBoxLayout(main_widget)

            ver_layout.setContentsMargins(9, 9, 9, 9)
            ver_layout.setSizeConstraint(ver_layout.SetDefaultConstraint)

            #button layout
            sub_widget = QWidget()
            sub_widget.setAccessibleName('sub_widget')

            ver_layout.addWidget(sub_widget)

            #client information layout
            context_label = QLabel()
            context_label.setText("Client information")
            ver_layout.addWidget(context_label)

            app_context_widget = QPlainTextEdit()
            app_context_widget.setObjectName(k.concert_alias + '_' +
                                             'app_context_widget')
            app_context_widget.setAccessibleName('app_context_widget')
            app_context_widget.appendHtml(k.get_rapp_context())
            app_context_widget.setReadOnly(True)

            cursor = app_context_widget.textCursor()
            cursor.movePosition(QTextCursor.Start, QTextCursor.MoveAnchor, 0)
            app_context_widget.setTextCursor(cursor)
            ver_layout.addWidget(app_context_widget)

            # new icon
            path = ""
            if k.is_new:
                # This only changes when the concert client changes topic publishes anew
                path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                    "../../resources/images/new.gif")

            #add tab
            self._widget.tabWidget.addTab(main_widget, QIcon(path),
                                          k.concert_alias)

        #set previous selected tab
        for k in range(self._widget.tabWidget.count()):
            tab_text = self._widget.tabWidget.tabText(k)
            if tab_text == self.pre_selected_client_name:
                self._widget.tabWidget.setCurrentIndex(k)
    def __init__(self, host, masteruri=None, parent=None):
        PackageDialog.__init__(self, parent)
        self.host = host
        self.setWindowTitle('Run')

        ns_name_label = QLabel("NS/Name:", self.content)
        self.ns_field = QComboBox(self.content)
        self.ns_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.ns_field.setEditable(True)
        ns_history = nm.history().cachedParamValues('run_dialog/NS')
        ns_history.insert(0, '/')
        self.ns_field.addItems(ns_history)
        self.name_field = QLineEdit(self.content)
        self.name_field.setEnabled(False)
        horizontalLayout = QHBoxLayout()
        horizontalLayout.addWidget(self.ns_field)
        horizontalLayout.addWidget(self.name_field)
        self.contentLayout.addRow(ns_name_label, horizontalLayout)
        args_label = QLabel("Args:", self.content)
        self.args_field = QComboBox(self.content)
        self.args_field.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength)
        self.args_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.args_field.setEditable(True)
        self.contentLayout.addRow(args_label, self.args_field)
        args_history = nm.history().cachedParamValues('run_dialog/Args')
        args_history.insert(0, '')
        self.args_field.addItems(args_history)

        host_label = QLabel("Host:", self.content)
        self.host_field = QComboBox(self.content)
#    self.host_field.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self.host_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.host_field.setEditable(True)
        host_label.setBuddy(self.host_field)
        self.contentLayout.addRow(host_label, self.host_field)
        self.host_history = host_history = nm.history().cachedParamValues('/Host')
        if self.host in host_history:
            host_history.remove(self.host)
        host_history.insert(0, self.host)
        self.host_field.addItems(host_history)

        master_label = QLabel("ROS Master URI:", self.content)
        self.master_field = QComboBox(self.content)
        self.master_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.master_field.setEditable(True)
        master_label.setBuddy(self.host_field)
        self.contentLayout.addRow(master_label, self.master_field)
        self.master_history = master_history = nm.history().cachedParamValues('/Optional Parameter/ROS Master URI')
        self.masteruri = "ROS_MASTER_URI" if masteruri is None else masteruri
        if self.masteruri in master_history:
            master_history.remove(self.masteruri)
        master_history.insert(0, self.masteruri)
        self.master_field.addItems(master_history)

#    self.package_field.setFocus(QtCore.Qt.TabFocusReason)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
        else:
            self.package_field.editTextChanged.connect(self.on_package_selected)
        self.binary_field.activated[str].connect(self.on_binary_selected)
Exemple #3
0
 def _create_buttons(self):
     # create the buttons line
     self.buttons = QWidget(self)
     self.horizontalLayout = QHBoxLayout(self.buttons)
     self.horizontalLayout.setContentsMargins(4, 0, 4, 0)
     self.horizontalLayout.setObjectName("horizontalLayout")
     # add the search button
     self.searchButton = QPushButton(self)
     self.searchButton.setObjectName("searchButton")
     #        self.searchButton.clicked.connect(self.on_shortcut_find)
     self.searchButton.toggled.connect(self.on_toggled_find)
     self.searchButton.setText(self._translate("&Find"))
     self.searchButton.setToolTip('Open a search dialog (Ctrl+F)')
     self.searchButton.setFlat(True)
     self.searchButton.setCheckable(True)
     self.horizontalLayout.addWidget(self.searchButton)
     # add the replace button
     self.replaceButton = QPushButton(self)
     self.replaceButton.setObjectName("replaceButton")
     #        self.replaceButton.clicked.connect(self.on_shortcut_replace)
     self.replaceButton.toggled.connect(self.on_toggled_replace)
     self.replaceButton.setText(self._translate("&Replace"))
     self.replaceButton.setToolTip('Open a search&replace dialog (Ctrl+R)')
     self.replaceButton.setFlat(True)
     self.replaceButton.setCheckable(True)
     self.horizontalLayout.addWidget(self.replaceButton)
     # add the goto button
     self.gotoButton = QPushButton(self)
     self.gotoButton.setObjectName("gotoButton")
     self.gotoButton.clicked.connect(self.on_shortcut_goto)
     self.gotoButton.setText(self._translate("&Goto line"))
     self.gotoButton.setShortcut("Ctrl+G")
     self.gotoButton.setToolTip('Open a goto dialog (Ctrl+G)')
     self.gotoButton.setFlat(True)
     self.horizontalLayout.addWidget(self.gotoButton)
     # add a tag button
     self.tagButton = self._create_tag_button(self)
     self.horizontalLayout.addWidget(self.tagButton)
     # add spacer
     spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding,
                              QSizePolicy.Minimum)
     self.horizontalLayout.addItem(spacerItem)
     # add line number label
     self.pos_label = QLabel()
     self.horizontalLayout.addWidget(self.pos_label)
     # add spacer
     spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding,
                              QSizePolicy.Minimum)
     self.horizontalLayout.addItem(spacerItem)
     # add save button
     self.saveButton = QPushButton(self)
     self.saveButton.setObjectName("saveButton")
     self.saveButton.clicked.connect(self.on_saveButton_clicked)
     self.saveButton.setText(self._translate("&Save"))
     self.saveButton.setShortcut("Ctrl+S")
     self.saveButton.setToolTip('Save the changes to the file (Ctrl+S)')
     self.saveButton.setFlat(True)
     self.horizontalLayout.addWidget(self.saveButton)
     return self.buttons
Exemple #4
0
def clearLayoutAndFixHeight(layout):
    # Clear all subfunction buttons.
    while layout.count():
        item = layout.takeAt(0)
        if item.widget() is not None:
            item.widget().deleteLater()
    height_label = QLabel()
    height_label.setFixedHeight(30)
    layout.addWidget(height_label)
Exemple #5
0
def clearLayoutAndFixHeight(layout):
    # Clear all subfunction buttons.
    while layout.count():
        item = layout.takeAt(0)
        if item.widget() is not None:
            item.widget().deleteLater()
    height_label = QLabel()
    height_label.setFixedHeight(30)
    layout.addWidget(height_label)
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Select Binary')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")

        self.content = QWidget()
        self.contentLayout = QFormLayout(self.content)
        self.contentLayout.setVerticalSpacing(0)
        self.verticalLayout.addWidget(self.content)

        self.packages = None

        package_label = QLabel("Package:", self.content)
        self.package_field = QComboBox(self.content)
        self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.package_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.package_field.setEditable(True)
        self.contentLayout.addRow(package_label, self.package_field)
        binary_label = QLabel("Binary:", self.content)
        self.binary_field = QComboBox(self.content)
#    self.binary_field.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self.binary_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.binary_field.setEditable(True)
        self.contentLayout.addRow(binary_label, self.binary_field)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)

        self.package_field.setFocus(Qt.TabFocusReason)
        self.package = ''
        self.binary = ''

        if self.packages is None:
            self.package_field.addItems(['packages searching...'])
            self.package_field.setCurrentIndex(0)
            self._fill_packages_thread = PackagesThread()
            self._fill_packages_thread.packages.connect(self._fill_packages)
            self._fill_packages_thread.start()

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        QMetaObject.connectSlotsByName(self)
        self.package_field.activated[str].connect(self.on_package_selected)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
            self.binary_field.textChanged.connect(self.on_binary_selected)
        else:
            self.package_field.editTextChanged.connect(self.on_package_selected)
            self.binary_field.editTextChanged.connect(self.on_binary_selected)
 def beginRosLabel(self,obj):
     pm,lm = self.__get_immediate_parent()
     
     fr = QFrame(pm)
     layout = QGridLayout()
     nlb = QLabel(obj.label_name + ":",fr)
     nlb.setToolTip(obj.topic_name)
     layout.addWidget(nlb,1,1)
     layout.addWidget(RosLabel(fr,obj.label_name,obj.topic_name,obj.topic_type,obj.topic_field),1,2)
     fr.setLayout(layout)
     
     lm.addWidget(fr)
    def __populate_self(self):
        i = 1
        if len(self.topic_fields) == 0:
            fields = RosHelper.get_all_msg_fields(self.topic_type)
        else:
            fields = self.topic_fields

        for field in fields:
            self.ref_dict[field] = QLabel("None", self)
            self.layout.addWidget(QLabel(field, self), i, 1)
            self.layout.addWidget(self.ref_dict[field], i, 2)
            i += 1
        self.setLayout(self.layout)
Exemple #9
0
    def beginRosLabel(self, obj):
        pm, lm = self.__get_immediate_parent()

        fr = QFrame(pm)
        layout = QGridLayout()
        nlb = QLabel(obj.label_name + ":", fr)
        nlb.setToolTip(obj.topic_name)
        layout.addWidget(nlb, 1, 1)
        layout.addWidget(
            RosLabel(fr, obj.label_name, obj.topic_name, obj.topic_type,
                     obj.topic_field), 1, 2)
        fr.setLayout(layout)

        lm.addWidget(fr)
    def __init__(self,
                 options,
                 title='Exclusive Options',
                 selected_index=None):
        super(ExclusiveOptionGroup, self).__init__()
        self.setTitle(title)
        self.setLayout(QVBoxLayout())
        self._button_group = QButtonGroup()
        self._button_group.setExclusive(True)
        self._options = options

        button_id = 0
        for option in self._options:
            button_id += 1

            radio_button = QRadioButton(
                option.get('title', 'option %d' % button_id))
            radio_button.setEnabled(option.get('enabled', True))
            radio_button.setChecked(
                option.get('selected', False)
                or (button_id - 1) == selected_index)
            radio_button.setToolTip(option.get('tooltip', ''))

            widget = QWidget()
            widget.setLayout(QVBoxLayout())
            widget.layout().addWidget(radio_button)
            if 'description' in option:
                widget.layout().addWidget(QLabel(option['description']))

            self._button_group.addButton(radio_button, button_id)
            self.layout().addWidget(widget)
Exemple #11
0
    def __init__(self,
                 options,
                 title='Checkboxes',
                 selected_indexes=[],
                 parent=None):
        super(CheckBoxGroup, self).__init__()
        self.setTitle(title)
        self.setLayout(QVBoxLayout())
        self._button_group = QButtonGroup()
        self._button_group.setExclusive(False)
        self._options = options
        if parent == None:
            parent = self

        for (button_id, option) in enumerate(self._options):

            checkbox = QCheckBox(option.get('title', 'option %d' % button_id))
            checkbox.setEnabled(option.get('enabled', True))
            checkbox.setChecked(button_id in selected_indexes)
            checkbox.setToolTip(option.get('tooltip', ''))

            self._button_group.addButton(checkbox, button_id)
            parent.layout().addWidget(checkbox)
            if 'description' in option:
                parent.layout().addWidget(QLabel(option['description']))
Exemple #12
0
    def _set_parameter_layout(self):

        params = self.admin_app_interface.get_srv_parameters(
            self.current_service['parameters_detail'])
        is_enabled = self.current_service['enabled']

        if self.params_layout_items:
            for item in self.params_layout_items:
                self.params_layout.removeWidget(item[0])
                self.params_layout.removeWidget(item[1])
                item[0].setParent(None)
                item[1].setParent(None)
            self.params_layout_items = []

        if params:
            self.params_layout.setColumnStretch(1, 0)
            self.params_layout.setRowStretch(2, 0)
            for param in params.keys():
                label = QLabel(param)
                self.params_layout.addWidget(label)
                value = QTextEdit(str(params[param]))
                value.setMaximumHeight(30)
                self.params_layout.addWidget(value)
                self.params_layout_items.append((label, value))

        self._set_enable_params_layout(not is_enabled)
Exemple #13
0
    def __init__(self, context):
        super(EusGUI, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName('EusGUI')
        self.msg = None
        # Create a container widget and give it a layout
        self._toolbar = QToolBar()
        self._toolbar.addWidget(QLabel('EusGUI'))
        self._container = QWidget()
        self._layout    = QVBoxLayout()
        self._container.setLayout(self._layout)
        
        self._layout.addWidget(self._toolbar)
        
        self._prev_button = QPushButton('PREV')
        self._prev_button.clicked.connect(self._prev_cb)
        self._layout.addWidget(self._prev_button)
        
        self._refresh_button = QPushButton('DO IT AGAIN')
        self._refresh_button.clicked.connect(self._refresh_cb)
        self._layout.addWidget(self._refresh_button)

        self._next_button = QPushButton('NEXT')
        self._next_button.clicked.connect(self._next_cb)
        self._layout.addWidget(self._next_button)
        context.add_widget(self._container)
Exemple #14
0
    def __init__(self, context):
        super(LevelSelectorPlugin, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName('LevelSelectorPlugin')

        # Create QWidget
        self._widget = QWidget()
        # self._widget.setFont(QFont("Times", 15, QFont.Bold))
        self._button_layout = QVBoxLayout(self._widget)

        self.buttons = []
        self.text_label = QLabel("Waiting for MultiLevelMapData...", self._widget)
        self._button_layout.addWidget(self.text_label)

        self._widget.setObjectName('LevelSelectorPluginUI')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))
        context.add_widget(self._widget)

        self.connect(self._widget, SIGNAL("update_buttons"), self.update_buttons)
        self.connect(self._widget, SIGNAL("update_button_status"), self.update_button_status)

        # Subcribe to the multi level map data to get information about all the maps.
        self.multimap_subscriber = rospy.Subscriber("map_metadata", MultiLevelMapData, self.process_multimap)
        self.levels = []
        self.current_level = None

        # Subscribe to the current level we are on.
        self.status_subscriber = None

        # Create a service proxy to change the current level.
        self.level_selector_proxy = rospy.ServiceProxy("level_mux/change_current_level", ChangeCurrentLevel)
        self.level_selector_proxy.wait_for_service()
    def __init__(self,
                 options,
                 title='Exclusive Options',
                 selected_index=None,
                 parent=None):
        super(ExclusiveOptionGroup, self).__init__()
        self.setTitle(title)
        self.setLayout(QVBoxLayout())
        self._button_group = QButtonGroup()
        self._button_group.setExclusive(True)
        self._options = options
        if parent == None:
            parent = self

        for (button_id, option) in enumerate(self._options):

            radio_button = QRadioButton(
                option.get('title', 'option %d' % button_id))
            radio_button.setEnabled(option.get('enabled', True))
            radio_button.setChecked(
                option.get('selected', False) or button_id == selected_index)
            radio_button.setToolTip(option.get('tooltip', ''))

            self._button_group.addButton(radio_button, button_id)
            parent.layout().addWidget(radio_button)
            if 'description' in option:
                parent.layout().addWidget(QLabel(option['description']))
Exemple #16
0
    def __init__(self, motion_publisher, robot_config):
        super(MotionEditorWidget, self).__init__()
        self.robot_config = robot_config
        self._motion_publisher = motion_publisher
        self._motion_data = MotionData(robot_config)
        self._filter_pattern = ''
        self._playback_marker = None
        self._playback_timer = None

        ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                               'motion_editor.ui')
        loadUi(ui_file, self)
        self.list_widgets = {}
        for group_type in robot_config.group_types():
            list_widget = QListWidget()
            list_widget.setSortingEnabled(True)
            list_widget.setDragDropMode(QAbstractItemView.DragOnly)
            list_widget.setContextMenuPolicy(Qt.CustomContextMenu)

            list_widget.customContextMenuRequested.connect(
                lambda pos, _group_type=group_type: self.
                positions_list_context_menu(_group_type, pos))
            list_widget.itemChanged.connect(self.on_list_item_changed)

            self.position_lists_layout.addWidget(list_widget)
            self.list_widgets[group_type] = list_widget

        self._timeline_widget = TimelineWidget()
        for track_name in self.robot_config.sorted_groups():
            track_type = self.robot_config.groups[track_name].group_type
            track = self._timeline_widget.add_track(track_name, track_type)

            list_widget = self.list_widgets[track_type]
            palette = list_widget.palette()
            palette.setColor(QPalette.Base, track._colors['track'])
            list_widget.setPalette(palette)

        self.timeline_group.layout().addWidget(self._timeline_widget)

        for group_type in robot_config.group_types():
            label = QLabel(group_type)
            label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            self.group_label_layout.addWidget(label)

        self.update_motion_name_combo()

        self.stop_motion_button.pressed.connect(self.on_motion_stop_pressed)
    def __init__(self, motion_publisher, robot_config):
        super(MotionEditorWidget, self).__init__()
        self.robot_config = robot_config
        self._motion_publisher = motion_publisher
        self._motion_data = MotionData(robot_config)
        self._filter_pattern = ''
        self._playback_marker = None
        self._playback_timer = None

        ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'motion_editor.ui')
        loadUi(ui_file, self)
        self.list_widgets = {}
        for group_type in robot_config.group_types():
            list_widget = QListWidget()
            list_widget.setSortingEnabled(True)
            list_widget.setDragDropMode(QAbstractItemView.DragOnly)
            list_widget.setContextMenuPolicy(Qt.CustomContextMenu)

            list_widget.customContextMenuRequested.connect(
                lambda pos, _group_type=group_type: self.positions_list_context_menu(_group_type, pos)
            )
            list_widget.itemChanged.connect(self.on_list_item_changed)

            self.position_lists_layout.addWidget(list_widget)
            self.list_widgets[group_type] = list_widget

        self._timeline_widget = TimelineWidget()
        for track_name in self.robot_config.sorted_groups():
            track_type = self.robot_config.groups[track_name].group_type
            track = self._timeline_widget.add_track(track_name, track_type)

            list_widget = self.list_widgets[track_type]
            palette = list_widget.palette()
            palette.setColor(QPalette.Base, track._colors['track'])
            list_widget.setPalette(palette)

        self.timeline_group.layout().addWidget(self._timeline_widget)

        for group_type in robot_config.group_types():
            label = QLabel(group_type)
            label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
            self.group_label_layout.addWidget(label)

        self.update_motion_name_combo()

        self.stop_motion_button.pressed.connect(self.on_motion_stop_pressed)
    def __init__(self, masteruri, cfg, ns, nodes, parent=None):
        QFrame.__init__(self, parent)
        self._masteruri = masteruri
        self._nodes = {cfg: {ns: nodes}}
        frame_layout = QVBoxLayout(self)
        frame_layout.setContentsMargins(0, 0, 0, 0)
        # create frame for warning label
        self.warning_frame = warning_frame = QFrame(self)
        warning_layout = QHBoxLayout(warning_frame)
        warning_layout.setContentsMargins(0, 0, 0, 0)
        warning_layout.addItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.warning_label = QLabel()
        icon = nm.settings().icon('crystal_clear_warning.png')
        self.warning_label.setPixmap(icon.pixmap(QSize(40, 40)))
        self.warning_label.setToolTip(
            'Multiple configuration for same node found!\nA first one will be selected for the start a node!'
        )
        warning_layout.addWidget(self.warning_label)
        warning_layout.addItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        frame_layout.addItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        frame_layout.addWidget(warning_frame)
        # create frame for start/stop buttons
        buttons_frame = QFrame()
        buttons_layout = QHBoxLayout(buttons_frame)
        buttons_layout.setContentsMargins(0, 0, 0, 0)
        buttons_layout.addItem(QSpacerItem(20, 20))
        self.on_button = QPushButton()
        self.on_button.setFlat(False)
        self.on_button.setText("On")
        self.on_button.clicked.connect(self.on_on_clicked)
        buttons_layout.addWidget(self.on_button)

        self.off_button = QPushButton()
        self.off_button.setFlat(True)
        self.off_button.setText("Off")
        self.off_button.clicked.connect(self.on_off_clicked)
        buttons_layout.addWidget(self.off_button)
        buttons_layout.addItem(QSpacerItem(20, 20))
        frame_layout.addWidget(buttons_frame)
        frame_layout.addItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.warning_frame.setVisible(False)
Exemple #19
0
    def _create_buttons(self):
        # create the buttons line
        self.buttons = QWidget(self)
        self.horizontalLayout = QHBoxLayout(self.buttons)
        self.horizontalLayout.setContentsMargins(4, 0, 4, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        # add the search button
        self.searchButton = QPushButton(self)
        self.searchButton.setObjectName("searchButton")
#        self.searchButton.clicked.connect(self.on_shortcut_find)
        self.searchButton.toggled.connect(self.on_toggled_find)
        self.searchButton.setText(self._translate("&Find"))
        self.searchButton.setToolTip('Open a search dialog (Ctrl+F)')
        self.searchButton.setFlat(True)
        self.searchButton.setCheckable(True)
        self.horizontalLayout.addWidget(self.searchButton)
        # add the replace button
        self.replaceButton = QPushButton(self)
        self.replaceButton.setObjectName("replaceButton")
#        self.replaceButton.clicked.connect(self.on_shortcut_replace)
        self.replaceButton.toggled.connect(self.on_toggled_replace)
        self.replaceButton.setText(self._translate("&Replace"))
        self.replaceButton.setToolTip('Open a search&replace dialog (Ctrl+R)')
        self.replaceButton.setFlat(True)
        self.replaceButton.setCheckable(True)
        self.horizontalLayout.addWidget(self.replaceButton)
        # add the goto button
        self.gotoButton = QPushButton(self)
        self.gotoButton.setObjectName("gotoButton")
        self.gotoButton.clicked.connect(self.on_shortcut_goto)
        self.gotoButton.setText(self._translate("&Goto line"))
        self.gotoButton.setShortcut("Ctrl+G")
        self.gotoButton.setToolTip('Open a goto dialog (Ctrl+G)')
        self.gotoButton.setFlat(True)
        self.horizontalLayout.addWidget(self.gotoButton)
        # add a tag button
        self.tagButton = self._create_tag_button(self)
        self.horizontalLayout.addWidget(self.tagButton)
        # add spacer
        spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        # add line number label
        self.pos_label = QLabel()
        self.horizontalLayout.addWidget(self.pos_label)
        # add spacer
        spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        # add save button
        self.saveButton = QPushButton(self)
        self.saveButton.setObjectName("saveButton")
        self.saveButton.clicked.connect(self.on_saveButton_clicked)
        self.saveButton.setText(self._translate("&Save"))
        self.saveButton.setShortcut("Ctrl+S")
        self.saveButton.setToolTip('Save the changes to the file (Ctrl+S)')
        self.saveButton.setFlat(True)
        self.horizontalLayout.addWidget(self.saveButton)
        return self.buttons
Exemple #20
0
 def add_info_no_screen(self, nodename):
     if self.questionid == self.TYPE_NOSCREEN:
         self.data.data.append(nodename)
         self.frameui.scrollAreaLayout.addWidget(QLabel(nodename))
     else:
         self._queue.add(self.TYPE_NOSCREEN, '', MessageData([nodename]))
         if self.questionid == self.TYPE_INVALID:
             self._new_request = self._read_next_item()
             self._frameui_4_request(self._new_request)
Exemple #21
0
 def __init__(self):
     super(StringLabelWidget, self).__init__()
     self.lock = Lock()
     vbox = QtGui.QVBoxLayout(self)
     self.label = QLabel()
     self.label.setAlignment(Qt.AlignLeft)
     self.label.setSizePolicy(
         QSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored))
     font = QFont("Helvetica", 14)
     self.label.setFont(font)
     self.label.setWordWrap(True)
     vbox.addWidget(self.label)
     self.string_sub = None
     self._string_topics = []
     self._update_topic_timer = QTimer(self)
     self._update_topic_timer.timeout.connect(self.updateTopics)
     self._update_topic_timer.start(1)
     self._active_topic = None
     self._dialog = ComboBoxDialog()
    def _load_parameter(self,param_index,param_name, param_type,param_value, param_min, param_max, param_desc):
        x_check = 160
        x ,y ,w ,h = 4,4 + 40 * param_index,150,20
        label = QLabel(param_name,self.parameters)
        label.setGeometry(x,y,w,h)
        label.setToolTip(param_desc)
        label.show()
        if param_type == 'Boolean':
            checkbox = QCheckBox('',self.parameters)
            checkbox.setGeometry(x_check,y,w,h)
            checkbox.setChecked(param_value == '1')
            checkbox.setToolTip(param_desc)
            checkbox.stateChanged.connect(partial(self._handle_bool_param_changed,param_name))
            checkbox.show()
        elif param_type == 'Integer':
            if len(param_min) > 0 and len(param_max) > 0 and int(param_max) < 5:
                slider = QSlider(Qt.Horizontal,self.parameters)
                slider.setMinimum(int(param_min))
                slider.setMaximum(int(param_max))
                slider.setValue(int(param_value))
                slider.setTickPosition(QSlider.TicksBelow)
                slider.setGeometry(x_check,y,w,h)
                slider.setToolTip(param_desc)
                slider.setTickInterval(1)
                slider.setSingleStep(1)
                slider.setPageStep(1)
                slider.valueChanged.connect(partial(self._handle_param_changed,param_name))
                slider.show()
            else:
                spin = QSpinBox(self.parameters)
                if len(param_min) > 0:
                    spin.setMinimum(int(param_min))
                if len(param_max) > 0:
                    spin.setMaximum(int(param_max))
                spin.setValue(int(param_value))
                spin.setToolTip(param_desc)
                spin.setGeometry(x_check,y,w,h)
                spin.valueChanged.connect(partial(self._handle_param_changed,param_name))
                spin.show()
        elif param_type == 'Double':
            spin = QDoubleSpinBox(self.parameters)
            if len(param_min) > 0:
                spin.setMinimum(float(param_min))
            if len(param_max) > 0:
                spin.setMaximum(float(param_max))
            spin.setValue(float(param_value))
            spin.valueChanged.connect(partial(self._handle_param_changed,param_name))
            spin.setGeometry(x_check,y,w,h)
            spin.show()
        elif param_type == 'String':
            lineEdit = QLineEdit(self.parameters)
            lineEdit.setText(param_value)
            lineEdit.setToolTip(param_desc)
            lineEdit.setGeometry(x_check,y,w,h)
            lineEdit.textChanged.connect(partial(self._handle_param_changed,param_name))
            lineEdit.show()

        self.parameters.update()
 def _create_replace_frame(self):
     # create frame with replace row
     self.rplc_frame = rplc_frame = QFrame(self)
     rplc_hbox_layout = QHBoxLayout(rplc_frame)
     rplc_hbox_layout.setContentsMargins(0, 0, 0, 0)
     rplc_hbox_layout.setSpacing(1)
     self.replace_field = EnchancedLineEdit(rplc_frame)
     self.replace_field.setPlaceholderText('replace text')
     self.replace_field.returnPressed.connect(self.on_replace)
     rplc_hbox_layout.addWidget(self.replace_field)
     self.replace_result_label = QLabel(rplc_frame)
     self.replace_result_label.setText(' ')
     rplc_hbox_layout.addWidget(self.replace_result_label)
     self.replace_button = replace_button = QPushButton("> &Replace >")
     replace_button.setFixedWidth(90)
     replace_button.clicked.connect(self.on_replace_click)
     rplc_hbox_layout.addWidget(replace_button)
     rplc_frame.setVisible(False)
     return rplc_frame
Exemple #24
0
class PingGUI(Plugin):
    def __init__(self, context):
        super(PingGUI, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName('PingGUI')
        self.msg = None
        # Create a container widget and give it a layout
        self._container = QWidget()
        self._layout    = QVBoxLayout()
        self._container.setLayout(self._layout)
        self._label = QLabel("xx ms latency")
        p = self._label.palette()
        p.setColor(self._label.backgroundRole(), Qt.red)
        self._label.setPalette(p)
        self._layout.addWidget(self._label)
        self.set_bg_color(100, 100, 100)
        
        rospy.Subscriber("/ping/delay", Float64, self.ping_cb)
        context.add_widget(self._container)
        self._update_plot_timer = QTimer(self)
        self._update_plot_timer.timeout.connect(self.update_gui)
        self._update_plot_timer.start(1)
    def update_gui(self):
        if not self.msg:
            return
        msg = self.msg
        # msec 
        # 100 -> green, 1000 -> red
        # normalize within 1000 ~ 100
        orig_latency = msg.data
        msg_data = orig_latency
        if msg.data > 1000:
            msg_data = 1000
        elif msg.data < 100:
            msg_data = 100
        ratio = (msg_data - 100) / (1000 - 100)
        color_r = ratio * 255.0
        color_g = (1 - ratio) * 255.0
        # devnull = open(os.devnull, "w")
        # with RedirectStdStreams(stdout=devnull, stderr=devnull):
        self.set_bg_color(color_r, color_g, 0)
        self._label.setText("%d ms latency" % (orig_latency))
    def set_bg_color(self, r, g, b):
        self._label.setStyleSheet("QLabel { display: block; background-color: rgba(%d, %d, %d, 255); text-align: center; font-size: 30px;}" % (r, g, b))
    def ping_cb(self, msg):
        self.msg = msg
    def shutdown_plugin(self):
        pass
    def save_settings(self, plugin_settings, instance_settings):
        pass
    def restore_settings(self, plugin_settings, instance_settings):
        pass
    def __init__(self,
                 default_mcast_group,
                 default_port,
                 networks_count,
                 parent=None):
        '''
        Creates an input dialog.
        @param default_port: the default discovery port
        @type default_port: C{int}
        @param networks_count: the count of discovering ports
        @type networks_count: C{int}
        '''
        QDialog.__init__(self, parent=parent)
        threading.Thread.__init__(self)
        self.default_port = default_port
        self.setObjectName('NetworkDiscoveryDialog')
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.setWindowFlags(Qt.Window)
        self.setWindowTitle('Network Discovery')
        self.resize(728, 512)
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout.setContentsMargins(1, 1, 1, 1)

        self.display = QTextBrowser(self)
        self.display.setReadOnly(True)
        self.verticalLayout.addWidget(self.display)
        self.display_clear_signal.connect(self.display.clear)
        self.display_append_signal.connect(self.display.append)
        self.display.anchorClicked.connect(self.on_anchorClicked)

        self.status_label = QLabel('0 messages', self)
        self.verticalLayout.addWidget(self.status_label)
        self.status_text_signal.connect(self.status_label.setText)
        self._msg_counts = dict()

        self._networks_count = networks_count
        self._running = True
        self._received_msgs = 0
        self._discovered = dict()
        self._hosts = dict()  # resolution for hostname and address
        self.mutex = threading.RLock()
        self.sockets = []
        with self.mutex:
            try:
                for p in range(networks_count):
                    msock = DiscoverSocket(default_port + p,
                                           default_mcast_group)
                    self.sockets.append(msock)
                    msock.settimeout(self.TIMEOUT)
            except Exception as e:
                self.display.setText(utf8(e))
        self.setDaemon(True)
        self.start()
Exemple #26
0
 def __init__(self, context):
     super(PingGUI, self).__init__(context)
     # Give QObjects reasonable names
     self.setObjectName('PingGUI')
     self.msg = None
     # Create a container widget and give it a layout
     self._container = QWidget()
     self._layout    = QVBoxLayout()
     self._container.setLayout(self._layout)
     self._label = QLabel("xx ms latency")
     p = self._label.palette()
     p.setColor(self._label.backgroundRole(), Qt.red)
     self._label.setPalette(p)
     self._layout.addWidget(self._label)
     self.set_bg_color(100, 100, 100)
     
     rospy.Subscriber("/ping/delay", Float64, self.ping_cb)
     context.add_widget(self._container)
     self._update_plot_timer = QTimer(self)
     self._update_plot_timer.timeout.connect(self.update_gui)
     self._update_plot_timer.start(1)
    def __init__(self, parent, fileName, top_widget_layout):

        self.controllers = []
        self.parent      = parent

        self.loadFile(fileName)


        print "Initialize controllers..."
        for controller in self.controllers:
            frame = QFrame()
            frame.setFrameShape(QFrame.StyledPanel);
            frame.setFrameShadow(QFrame.Raised);

            vbox = QVBoxLayout()
            label = QLabel()
            label.setText(controller.label)
            vbox.addWidget(label);

            print controller.name

            for joint in controller.joints:
                label = QLabel()
                label.setText(joint.name)
                vbox.addWidget(label);

                #Add input for setting the biases
                widget = QWidget()
                hbox = QHBoxLayout()

                hbox.addWidget(joint.sensor_bias_spinbox)
                hbox.addWidget(joint.control_bias_spinbox)
                hbox.addWidget(joint.gearing_bias_spinbox)

                widget.setLayout(hbox)
                vbox.addWidget(widget)

            label = QLabel()
            label.setText("      Sensor           Control           Gearing")
            vbox.addWidget(label);
            vbox.addStretch()

            frame.setLayout(vbox)
            top_widget_layout.addWidget(frame)
        print "Done loading controllers"
Exemple #28
0
    def __init__(self):
        super(CalibrationMovementsGUI, self).__init__()
        move_group_name = rospy.get_param('~move_group', 'manipulator')
        self.angle_delta = math.radians(
            rospy.get_param('~rotation_delta_degrees', 25))
        self.translation_delta = rospy.get_param('~translation_delta_meters',
                                                 0.1)
        max_velocity_scaling = rospy.get_param('~max_velocity_scaling', 0.5)
        max_acceleration_scaling = rospy.get_param('~max_acceleration_scaling',
                                                   0.5)
        self.local_mover = CalibrationMovements(move_group_name,
                                                max_velocity_scaling,
                                                max_acceleration_scaling)
        self.current_pose = -1
        self.current_plan = None
        self.state = CalibrationMovementsGUI.NOT_INITED_YET

        self.layout = QVBoxLayout()
        self.labels_layout = QHBoxLayout()
        self.buttons_layout = QHBoxLayout()

        self.progress_bar = QProgressBar()
        self.pose_number_lbl = QLabel('0/8')
        self.bad_plan_lbl = QLabel('No plan yet')
        self.guide_lbl = QLabel('Hello')
        self.guide_lbl.setWordWrap(True)

        self.check_start_pose_btn = QPushButton('Check starting pose')
        self.check_start_pose_btn.clicked.connect(
            self.handle_check_current_state)

        self.next_pose_btn = QPushButton('Next Pose')
        self.next_pose_btn.clicked.connect(self.handle_next_pose)

        self.plan_btn = QPushButton('Plan')
        self.plan_btn.clicked.connect(self.handle_plan)

        self.execute_btn = QPushButton('Execute')
        self.execute_btn.clicked.connect(self.handle_execute)

        self.labels_layout.addWidget(self.pose_number_lbl)
        self.labels_layout.addWidget(self.bad_plan_lbl)

        self.buttons_layout.addWidget(self.check_start_pose_btn)
        self.buttons_layout.addWidget(self.next_pose_btn)
        self.buttons_layout.addWidget(self.plan_btn)
        self.buttons_layout.addWidget(self.execute_btn)

        self.layout.addWidget(self.progress_bar)
        self.layout.addLayout(self.labels_layout)
        self.layout.addWidget(self.guide_lbl)
        self.layout.addLayout(self.buttons_layout)

        self.setLayout(self.layout)

        self.plan_btn.setEnabled(False)
        self.execute_btn.setEnabled(False)

        self.setWindowTitle('Local Mover')
        self.show()
Exemple #29
0
    def __init__(self, context):
        super(LevelSelectorPlugin, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName('LevelSelectorPlugin')

        # Create QWidget
        self._widget = QWidget()
        # self._widget.setFont(QFont("Times", 15, QFont.Bold))
        self._button_layout = QVBoxLayout(self._widget)

        self.buttons = []
        self.text_label = QLabel("Waiting for MultiLevelMapData...",
                                 self._widget)
        self._button_layout.addWidget(self.text_label)

        self._widget.setObjectName('LevelSelectorPluginUI')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' (%d)' % context.serial_number()))
        context.add_widget(self._widget)

        self.connect(self._widget, SIGNAL("update_buttons"),
                     self.update_buttons)
        self.connect(self._widget, SIGNAL("update_button_status"),
                     self.update_button_status)

        # Subcribe to the multi level map data to get information about all the maps.
        self.multimap_subscriber = rospy.Subscriber("map_metadata",
                                                    MultiLevelMapData,
                                                    self.process_multimap)
        self.levels = []
        self.current_level = None

        # Subscribe to the current level we are on.
        self.status_subscriber = None

        # Create a service proxy to change the current level.
        self.level_selector_proxy = rospy.ServiceProxy(
            "level_mux/change_current_level", ChangeCurrentLevel)
        self.level_selector_proxy.wait_for_service()
    def __init__(self, context):
        super(ImageSnapShotGUI, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName('ImageSnapShotGUI')

        # Process standalone plugin command-line arguments
        from argparse import ArgumentParser
        parser = ArgumentParser()
        # Add argument(s) to the parser.
        parser.add_argument("-q", "--quiet", action="store_true",
                            dest="quiet",
                            help="Put plugin in silent mode")
        args, unknowns = parser.parse_known_args(context.argv())
        self._toolbar = QToolBar()
        self._toolbar.addWidget(QLabel('ImageSnapShot'))

        # Create a container widget and give it a layout
        self._container = QWidget()
        self._layout    = QVBoxLayout()
        self._container.setLayout(self._layout)
        self._layout.addWidget(self._toolbar)

        # Add a button for ....
        self._go_button = QPushButton('Head')
        self._go_button.clicked.connect(self._head)
        self._layout.addWidget(self._go_button)

        self._clear_button = QPushButton('Larm')
        self._clear_button.clicked.connect(self._larm)
        self._layout.addWidget(self._clear_button)

        self._clear_button = QPushButton('Rarm')
        self._clear_button.clicked.connect(self._rarm)
        self._layout.addWidget(self._clear_button)

        self._clear_button = QPushButton('L FishEye')
        self._clear_button.clicked.connect(self._lfisheye)
        self._layout.addWidget(self._clear_button)

        self._clear_button = QPushButton('R FishEye')
        self._clear_button.clicked.connect(self._rfisheye)
        self._layout.addWidget(self._clear_button)

        # self._step_run_button.setStyleSheet('QPushButton {color: black}')
        context.add_widget(self._container)

        self._head_pub = rospy.Publisher('/head_snap/snapshot', std_msgs.msg.Empty)
        self._lhand_pub = rospy.Publisher('/lhand_snap/snapshot', std_msgs.msg.Empty)
        self._rhand_pub = rospy.Publisher('/rhand_snap/snapshot', std_msgs.msg.Empty)
        self._lfisheye_pub = rospy.Publisher('/lfisheye_snap/snapshot', std_msgs.msg.Empty)
        self._rfisheye_pub = rospy.Publisher('/rfisheye_snap/snapshot', std_msgs.msg.Empty)
Exemple #31
0
    def startAreaEdit(self, edit_type):

        if self.editing_properties:
            self.endPropertyEdit()

        self.editing_area = True

        if edit_type == LocationFunction.ADD_LOCATION_AREA:
            self.edit_existing_location = None
        # else edit_existing_location was set to the correct location by startPropertyEdit()

        # Make sure all active selections have been cleared.
        self.clearAreaSelection()

        # If we're going to edit an existing area, stop drawing it and copy it to the active selection.
        if self.edit_existing_location is not None:
            self.draw_location[self.edit_existing_location] = False
            self.current_selection = QPolygon(
                self.locations[self.edit_existing_location])
            self.edit_existing_location = self.edit_existing_location

        # Setup the buttons in the configuration toolbar, and disable the original buttons to edit an area.
        clearLayoutAndFixHeight(self.configuration_layout)
        for button_text in ["Done", "Cancel"]:
            button = QPushButton(button_text, self.widget)
            button.clicked[bool].connect(partial(self.endAreaEdit,
                                                 button_text))
            self.configuration_layout.addWidget(button)
        self.current_selection_label = QLabel(self.widget)
        self.configuration_layout.addWidget(self.current_selection_label)
        self.configuration_layout.addStretch(1)

        self.edit_area_button[LocationFunction.ADD_LOCATION_AREA].setEnabled(
            False)
        self.edit_area_button[LocationFunction.EDIT_EXISTING_AREA].setEnabled(
            False)

        self.updateOverlay()
    def __init__(self, main, fileName, main_hbox):
        self.main       = main
        self.chain      = []
        self.poses      = []
        self.chain_name  = ""
        frame = QFrame()
        frame.setFrameShape(QFrame.StyledPanel);
        frame.setFrameShadow(QFrame.Raised);

        vbox = QVBoxLayout()

        label = QLabel()
        vbox.addWidget(label);

        self.load_file(fileName, vbox)
        self.trajectoryPublisher = rospy.Publisher('/trajectory_controllers/'+self.chain_name+'_traj_controller/trajectory'  ,JointTrajectory, queue_size=10)
        self.positionPublisher   = rospy.Publisher('/trajectory_controllers/'+self.chain_name+'_traj_controller/joint_states',JointState,      queue_size=10)
        self.ghostPublisher      = rospy.Publisher('/flor/ghost/set_joint_states',JointState, queue_size=10)

        label.setText(self.chain_name)
        vbox.addStretch(1)

        frame.setLayout(vbox)
        main_hbox.addWidget(frame)
Exemple #33
0
def create_label_textedit_pair(key, value):

    param_layout = QHBoxLayout()

    name_widget = QLabel(key)
    textedit_widget = QTextEdit()
    textedit_widget.setSizePolicy(QSizePolicy.MinimumExpanding,
                                  QSizePolicy.Ignored)
    textedit_widget.setMinimumSize(0, 30)
    textedit_widget.append(str(value))

    param_layout.addWidget(name_widget)
    param_layout.addWidget(textedit_widget)

    return param_layout
 def _create_find_frame(self):
     find_frame = QFrame(self)
     find_hbox_layout = QHBoxLayout(find_frame)
     find_hbox_layout.setContentsMargins(0, 0, 0, 0)
     find_hbox_layout.setSpacing(1)
     self.search_field = EnchancedLineEdit(find_frame)
     self.search_field.setPlaceholderText('search text')
     self.search_field.textChanged.connect(self.on_search_text_changed)
     self.search_field.returnPressed.connect(self.on_search)
     find_hbox_layout.addWidget(self.search_field)
     self.search_result_label = QLabel(find_frame)
     self.search_result_label.setText(' ')
     find_hbox_layout.addWidget(self.search_result_label)
     self.find_button_back = QPushButton("<")
     self.find_button_back.setFixedWidth(44)
     self.find_button_back.clicked.connect(self.on_search_back)
     find_hbox_layout.addWidget(self.find_button_back)
     self.find_button = QPushButton(">")
     self.find_button.setDefault(True)
     # self.find_button.setFlat(True)
     self.find_button.setFixedWidth(44)
     self.find_button.clicked.connect(self.on_search)
     find_hbox_layout.addWidget(self.find_button)
     return find_frame
 def __init__(self,
              nodename,
              masteruri,
              loggername,
              level='INFO',
              parent=None):
     '''
     Creates a new item.
     '''
     QFrame.__init__(self, parent)
     self.setObjectName("LoggerItem")
     self.nodename = nodename
     self.masteruri = masteruri
     self.loggername = loggername
     self.current_level = None
     layout = QHBoxLayout(self)
     layout.setContentsMargins(1, 1, 1, 1)
     self.debug = QRadioButton()
     self.debug.setStyleSheet(
         "QRadioButton{ background-color: #39B54A;}")  # QColor(57, 181, 74)
     self.debug.toggled.connect(self.toggled_debug)
     layout.addWidget(self.debug)
     self.info = QRadioButton()
     self.info.setStyleSheet("QRadioButton{ background-color: #FFFAFA;}")
     self.info.toggled.connect(self.toggled_info)
     layout.addWidget(self.info)
     self.warn = QRadioButton()
     self.warn.setStyleSheet(
         "QRadioButton{ background-color: #FFC706;}")  # QColor(255, 199, 6)
     self.warn.toggled.connect(self.toggled_warn)
     layout.addWidget(self.warn)
     self.error = QRadioButton()
     self.error.setStyleSheet(
         "QRadioButton{ background-color: #DE382B;}")  # QColor(222, 56, 43)
     self.error.toggled.connect(self.toggled_error)
     layout.addWidget(self.error)
     self.fatal = QRadioButton()
     self.fatal.setStyleSheet("QRadioButton{ background-color: #FF0000;}")
     self.fatal.toggled.connect(self.toggled_fatal)
     layout.addWidget(self.fatal)
     self.label = QLabel(loggername)
     layout.addWidget(self.label)
     layout.addStretch()
     self._callback = None  # used to set all logger
     self.success_signal.connect(self.on_succes_update)
     self.error_signal.connect(self.on_error_update)
     self.set_level(level)
    def __init__(self):
        super(CalibrationMovementsGUI, self).__init__()
        self.handeye_client = HandeyeClient()
        self.current_target_pose = -1  # -1 is home
        self.target_poses = None
        self.plan_was_successful = None
        self.state = CalibrationMovementsGUI.NOT_INITED_YET

        self.layout = QVBoxLayout()
        self.labels_layout = QHBoxLayout()
        self.buttons_layout = QHBoxLayout()

        self.progress_bar = QProgressBar()
        self.pose_number_lbl = QLabel('0/0')
        self.bad_plan_lbl = QLabel('No plan yet')
        self.bad_plan_lbl.setAlignment(Qt.AlignCenter)
        self.guide_lbl = QLabel('Hello')
        self.guide_lbl.setWordWrap(True)

        self.check_start_pose_btn = QPushButton('Check starting pose')
        self.check_start_pose_btn.clicked.connect(
            self.handle_check_current_state)

        self.next_pose_btn = QPushButton('Next Pose')
        self.next_pose_btn.clicked.connect(self.handle_next_pose)

        self.plan_btn = QPushButton('Plan')
        self.plan_btn.clicked.connect(self.handle_plan)

        self.execute_btn = QPushButton('Execute')
        self.execute_btn.clicked.connect(self.handle_execute)

        self.labels_layout.addWidget(self.pose_number_lbl)
        self.labels_layout.addWidget(self.bad_plan_lbl)

        self.buttons_layout.addWidget(self.check_start_pose_btn)
        self.buttons_layout.addWidget(self.next_pose_btn)
        self.buttons_layout.addWidget(self.plan_btn)
        self.buttons_layout.addWidget(self.execute_btn)

        self.layout.addWidget(self.progress_bar)
        self.layout.addLayout(self.labels_layout)
        self.layout.addWidget(self.guide_lbl)
        self.layout.addLayout(self.buttons_layout)

        self.setLayout(self.layout)

        self.plan_btn.setEnabled(False)
        self.execute_btn.setEnabled(False)

        self.setWindowTitle('Local Mover')
        self.show()
Exemple #37
0
 def _read_next_item(self):
     (qid, text, data) = self._queue.get()
     if qid == self.TYPE_NOSCREEN:
         self.questionid = self.TYPE_NOSCREEN
         self.text = 'No screens found! See log for details!<br>The following nodes are affected:'
         self.data = data
         self.frameui.questionIcon.setPixmap(self.IMAGES[qid])
         self.frameui.questionLabel.setText(self.text)
         for nodename in data.data:
             self.frameui.scrollAreaLayout.addWidget(QLabel(nodename))
         self.frameui.scrollArea.setVisible(True)
     elif qid != self.TYPE_INVALID:
         self.questionid = qid
         self.text = text
         self.data = data
         self.frameui.questionIcon.setPixmap(self.IMAGES[qid])
         self.frameui.questionLabel.setText(text)
     return qid != self.TYPE_INVALID
    def __init__(self, buttonProgramArrayIterator):
        
        super(ButtonSetPopupSelector, self).__init__();

        self.setStyleSheet(SpeakEasyGUI.stylesheetAppBG);
        
        self.programButtonDict = {};
        self.buttonProgramArrayIt = buttonProgramArrayIterator;
        self.buttonProgramArrays = []; # saved ButtonProgram arrays
        self.shownLabelArrays = [];
        self.currentlyShowingSetIndex = None;
        self.rootLayout = None;
        
        self.cancelButton = QPushButton("Cancel");
        self.cancelButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet);
        self.cancelButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT);
        #self.cancelButton.clicked.connect(partial(QDialog.done, self, 0));
        self.cancelButton.clicked.connect(self.clickedCancelButton);
        
        self.OKButton = QPushButton("Pick this One");
        self.OKButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet);
        self.OKButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT);
        self.OKButton.clicked.connect(self.clickedOKButton);
        
        self.currentNextPrevDirection = NextPrev.NEXT;

        self.nextButton = QPushButton("Next");
        self.nextButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet);
        self.nextButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT);
        self.nextButton.clicked.connect(self.clickedNextButton);

        self.prevButton = QPushButton("Previous");
        self.prevButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet);
        self.prevButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT);
        self.prevButton.clicked.connect(self.clickedPrevButton);

        self.setNextPrevButtonsEnabledness();
        
        self.endOfSetsLabel = QLabel("<b>No more button sets.</b>")
        self.noSetsLabel = QLabel("<b>No button sets available.</b>")

        self.noAvailableSets = False;
        self.offerNewButtonSet();
 def _create_replace_frame(self):
     # create frame with replace row
     self.rplc_frame = rplc_frame = QFrame(self)
     rplc_hbox_layout = QHBoxLayout(rplc_frame)
     rplc_hbox_layout.setContentsMargins(0, 0, 0, 0)
     rplc_hbox_layout.setSpacing(1)
     self.replace_field = EnchancedLineEdit(rplc_frame)
     self.replace_field.setPlaceholderText('replace text')
     self.replace_field.returnPressed.connect(self.on_replace)
     rplc_hbox_layout.addWidget(self.replace_field)
     self.replace_result_label = QLabel(rplc_frame)
     self.replace_result_label.setText(' ')
     rplc_hbox_layout.addWidget(self.replace_result_label)
     self.replace_button = replace_button = QPushButton("> &Replace >")
     replace_button.setFixedWidth(90)
     replace_button.clicked.connect(self.on_replace_click)
     rplc_hbox_layout.addWidget(replace_button)
     rplc_frame.setVisible(False)
     return rplc_frame
Exemple #40
0
    def startPropertyEdit(self):

        self.editing_properties = True
        self.edit_existing_location = self.edit_properties_location

        self.edit_area_button[LocationFunction.ADD_LOCATION_AREA].setEnabled(
            True)
        self.edit_area_button[LocationFunction.EDIT_EXISTING_AREA].setEnabled(
            True)

        # Construct the configuration layout.
        clearLayoutAndFixHeight(self.configuration_layout)

        neighbors_str = makeNeighborsString(
            self.locations[self.edit_properties_location], self.locations)
        self.update_name_label = QLabel(
            "Location (" + self.edit_properties_location + " - " +
            neighbors_str + ")      New Name: ", self.widget)
        self.configuration_layout.addWidget(self.update_name_label)

        self.update_name_textedit = QLineEdit(self.widget)
        self.update_name_textedit.setText(self.edit_properties_location)
        self.update_name_textedit.textEdited.connect(
            self.locationNameTextEdited)
        self.configuration_layout.addWidget(self.update_name_textedit)

        self.update_name_button = QPushButton("Update location Name",
                                              self.widget)
        self.update_name_button.clicked[bool].connect(self.updateLocationName)
        self.update_name_button.setEnabled(False)
        self.configuration_layout.addWidget(self.update_name_button)

        self.remove_location_button = QPushButton("Remove Location",
                                                  self.widget)
        self.remove_location_button.clicked[bool].connect(
            self.removeCurrentLocation)
        self.configuration_layout.addWidget(self.remove_location_button)

        self.configuration_layout.addStretch(1)

        self.updateOverlay()
Exemple #41
0
    def __init__(self, context):
        super(PingGUI, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName("PingGUI")
        self.msg = None
        # Create a container widget and give it a layout
        self._container = QWidget()
        self._layout = QVBoxLayout()
        self._container.setLayout(self._layout)
        self._label = QLabel("xx ms latency")
        p = self._label.palette()
        p.setColor(self._label.backgroundRole(), Qt.red)
        self._label.setPalette(p)
        self._layout.addWidget(self._label)
        self.set_bg_color(100, 100, 100)

        rospy.Subscriber("/ping/delay", Float64, self.ping_cb)
        context.add_widget(self._container)
        self._update_plot_timer = QTimer(self)
        self._update_plot_timer.timeout.connect(self.update_gui)
        self._update_plot_timer.start(1)
    def __init__(self, masteruri, cfg, ns, nodes, parent=None):
        QFrame.__init__(self, parent)
        self._masteruri = masteruri
        self._nodes = {cfg: {ns: nodes}}
        frame_layout = QVBoxLayout(self)
        frame_layout.setContentsMargins(0, 0, 0, 0)
        # create frame for warning label
        self.warning_frame = warning_frame = QFrame(self)
        warning_layout = QHBoxLayout(warning_frame)
        warning_layout.setContentsMargins(0, 0, 0, 0)
        warning_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.warning_label = QLabel()
        icon = QIcon(':/icons/crystal_clear_warning.png')
        self.warning_label.setPixmap(icon.pixmap(QSize(40, 40)))
        self.warning_label.setToolTip('Multiple configuration for same node found!\nA first one will be selected for the start a node!')
        warning_layout.addWidget(self.warning_label)
        warning_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        frame_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        frame_layout.addWidget(warning_frame)
        # create frame for start/stop buttons
        buttons_frame = QFrame()
        buttons_layout = QHBoxLayout(buttons_frame)
        buttons_layout.setContentsMargins(0, 0, 0, 0)
        buttons_layout.addItem(QSpacerItem(20, 20))
        self.on_button = QPushButton()
        self.on_button.setFlat(False)
        self.on_button.setText("On")
        self.on_button.clicked.connect(self.on_on_clicked)
        buttons_layout.addWidget(self.on_button)

        self.off_button = QPushButton()
        self.off_button.setFlat(True)
        self.off_button.setText("Off")
        self.off_button.clicked.connect(self.on_off_clicked)
        buttons_layout.addWidget(self.off_button)
        buttons_layout.addItem(QSpacerItem(20, 20))
        frame_layout.addWidget(buttons_frame)
        frame_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.warning_frame.setVisible(False)
 def _create_find_frame(self):
     find_frame = QFrame(self)
     find_hbox_layout = QHBoxLayout(find_frame)
     find_hbox_layout.setContentsMargins(0, 0, 0, 0)
     find_hbox_layout.setSpacing(1)
     self.search_field = EnchancedLineEdit(find_frame)
     self.search_field.setPlaceholderText('search text')
     self.search_field.textChanged.connect(self.on_search_text_changed)
     self.search_field.returnPressed.connect(self.on_search)
     find_hbox_layout.addWidget(self.search_field)
     self.search_result_label = QLabel(find_frame)
     self.search_result_label.setText(' ')
     find_hbox_layout.addWidget(self.search_result_label)
     self.find_button_back = QPushButton("<")
     self.find_button_back.setFixedWidth(44)
     self.find_button_back.clicked.connect(self.on_search_back)
     find_hbox_layout.addWidget(self.find_button_back)
     self.find_button = QPushButton(">")
     self.find_button.setDefault(True)
     # self.find_button.setFlat(True)
     self.find_button.setFixedWidth(44)
     self.find_button.clicked.connect(self.on_search)
     find_hbox_layout.addWidget(self.find_button)
     return find_frame
    def __init__(self, context):
        # super(BDIPelvisPoseWidget, self).__init__(context)
        # self.setObjectName('BDIPelvisPoseWidget')
        super(BDIPelvisPoseWidget, self).__init__()
        self.name = "BDIPelvisPoseWidget"

        self.updateStateSignal.connect(self.on_updateState)

        # self._widget = QWidget()
        self._widget = context
        vbox = QVBoxLayout()

        self.forward_position = 0.0
        self.lateral_position = 0.0
        self.height_position = 0.91
        self.roll_position = 0.0
        self.pitch_position = 0.0
        self.yaw_position = 0.0

        self.currentForward = 0.0
        self.currentLateral = 0.0
        self.currentHeight = 0.91
        self.currentRoll = 0.0
        self.currentPitch = 0.0
        self.currentYaw = 0.0
        # Define checkboxes
        vbox = QVBoxLayout()
        label = QLabel()
        label.setText("BDI Pelvis Height (Manipulate Mode Only)")  # todo - connect controller mode
        vbox.addWidget(label)

        self.enable_checkbox = QCheckBox("Enable")
        self.enable_checkbox.stateChanged.connect(self.on_enable_check)
        vbox.addWidget(self.enable_checkbox)

        self.snap_to_current_button = QPushButton("Snap to Current")
        self.snap_to_current_button.pressed.connect(self.on_snapCurrentPressed)
        vbox.addWidget(self.snap_to_current_button)

        self.roll_slider = QSlider(Qt.Horizontal)
        self.roll_label = QLabel()
        self.roll_label.setText("Roll")
        vbox.addWidget(self.roll_label)

        self.roll_slider.setRange(int(-100), int(101))
        self.roll_slider.setValue(int(0))
        self.roll_slider.setSingleStep((200) / 50)
        self.roll_slider.setTickInterval(25)
        self.roll_slider.valueChanged.connect(self.on_rollSliderMoved)
        vbox.addWidget(self.roll_slider)

        self.roll_progress_bar = QProgressBar()
        self.roll_progress_bar.setRange(int(-100), int(101))
        self.roll_progress_bar.setValue((6.0 / math.pi) * self.currentRoll * 100)
        self.roll_progress_bar.setFormat("%.6f" % self.currentRoll)
        vbox.addWidget(self.roll_progress_bar)

        self.pitch_slider = QSlider(Qt.Horizontal)
        self.pitch_label = QLabel()
        self.pitch_label.setText("Pitch")
        vbox.addWidget(self.pitch_label)

        self.pitch_slider.setRange(int(-100), int(101))
        self.pitch_slider.setValue(int(0))
        self.pitch_slider.setSingleStep((200) / 50)
        self.pitch_slider.setTickInterval(25)
        self.pitch_slider.valueChanged.connect(self.on_pitchSliderMoved)
        vbox.addWidget(self.pitch_slider)

        self.pitch_progress_bar = QProgressBar()
        self.pitch_progress_bar.setRange(int(-100), int(101))
        self.pitch_progress_bar.setValue((6.0 / math.pi) * self.currentPitch * 100)
        self.pitch_progress_bar.setFormat("%.6f" % self.currentPitch)
        vbox.addWidget(self.pitch_progress_bar)

        self.yaw_slider = QSlider(Qt.Horizontal)
        self.yaw_label = QLabel()
        self.yaw_label.setText("Yaw")
        vbox.addWidget(self.yaw_label)

        self.yaw_slider.setRange(int(-100), int(101))
        self.yaw_slider.setValue(int(0))
        self.yaw_slider.setSingleStep((200) / 50)
        self.yaw_slider.setTickInterval(25)
        self.yaw_slider.valueChanged.connect(self.on_yawSliderMoved)
        vbox.addWidget(self.yaw_slider)

        self.yaw_progress_bar = QProgressBar()
        self.yaw_progress_bar.setRange(int(-100), int(101))
        self.yaw_progress_bar.setValue((4.0 / math.pi) * self.currentYaw * 100)
        self.yaw_progress_bar.setFormat("%.6f" % self.currentYaw)
        vbox.addWidget(self.yaw_progress_bar)

        self.forward_label = QLabel()
        self.forward_label.setText("Forward")
        vbox.addWidget(self.forward_label)

        widget = QWidget()
        hbox = QHBoxLayout()
        hbox.addStretch()
        self.forward_slider = QSlider(Qt.Vertical)
        # self.forward_slider.setText("Height")
        self.forward_slider.setRange(int(-101), int(100))
        self.forward_slider.setValue(int(0))
        self.forward_slider.setSingleStep(1)
        self.forward_slider.setTickInterval(10)
        self.forward_slider.valueChanged.connect(self.on_forwardSliderMoved)
        hbox.addWidget(self.forward_slider)

        self.forward_progress_bar = QProgressBar()
        self.forward_progress_bar.setOrientation(Qt.Vertical)
        self.forward_progress_bar.setRange(int(-100), int(101))
        self.forward_progress_bar.setValue((self.currentForward / 0.075) * 100)
        self.forward_progress_bar.setTextVisible(False)
        hbox.addWidget(self.forward_progress_bar)

        self.forward_progress_bar_label = QLabel()
        self.forward_progress_bar_label.setText("%.6f" % self.currentForward)
        hbox.addWidget(self.forward_progress_bar_label)
        hbox.addStretch()
        widget.setLayout(hbox)
        vbox.addWidget(widget)

        self.lateral_label = QLabel()
        self.lateral_label.setText("Lateral")
        vbox.addWidget(self.lateral_label)

        self.lateral_slider = QSlider(Qt.Horizontal)
        # self.lateral_slider.setText("Lateral")
        self.lateral_slider.setRange(int(-100), int(101))
        self.lateral_slider.setValue(int(0))
        self.lateral_slider.setSingleStep((200) / 50)
        self.lateral_slider.setTickInterval(25)
        self.lateral_slider.valueChanged.connect(self.on_lateralSliderMoved)
        vbox.addWidget(self.lateral_slider)

        self.lateral_progress_bar = QProgressBar()
        self.lateral_progress_bar.setRange(int(-100), int(101))
        self.lateral_progress_bar.setValue((self.currentLateral / 0.15) * 100)
        self.lateral_progress_bar.setFormat("%.6f" % self.currentLateral)
        vbox.addWidget(self.lateral_progress_bar)

        self.height_label = QLabel()
        self.height_label.setText("Height")
        vbox.addWidget(self.height_label)

        widget = QWidget()
        hbox = QHBoxLayout()
        hbox.addStretch()
        self.height_slider = QSlider(Qt.Vertical)
        # self.height_slider.setText("Height")
        self.height_slider.setRange(int(55), int(105))
        self.height_slider.setValue(int(91))
        self.height_slider.setSingleStep(2)
        self.height_slider.setTickInterval(10)
        self.height_slider.valueChanged.connect(self.on_heightSliderMoved)
        hbox.addWidget(self.height_slider)

        self.height_progress_bar = QProgressBar()
        self.height_progress_bar.setOrientation(Qt.Vertical)
        self.height_progress_bar.setRange(int(55), int(105))
        self.height_progress_bar.setValue(self.currentHeight * 100)
        self.height_progress_bar.setTextVisible(False)
        hbox.addWidget(self.height_progress_bar)

        self.height_progress_bar_label = QLabel()
        self.height_progress_bar_label.setText("%.6f" % self.currentHeight)
        hbox.addWidget(self.height_progress_bar_label)
        hbox.addStretch()
        widget.setLayout(hbox)
        vbox.addWidget(widget)
        vbox.addStretch()

        self._widget.setLayout(vbox)
        # context.add_widget(self._widget)
        self.height_position = 0.91
        self.lateral_position = 0.0
        self.yaw_position = 0.0
        self.first_time = True
        self.enable_checkbox.setChecked(False)
        self.yaw_slider.setEnabled(False)
        self.roll_slider.setEnabled(False)
        self.pitch_slider.setEnabled(False)
        self.forward_slider.setEnabled(False)
        self.lateral_slider.setEnabled(False)
        self.height_slider.setEnabled(False)

        self.pub_robot = rospy.Publisher("/flor/controller/bdi_desired_pelvis_pose", PoseStamped, queue_size=10)
        # self.stateSubscriber = rospy.Subscriber('/flor/pelvis_controller/current_states',JointState, self.stateCallbackFnc)
        # self.pub_bdi_pelvis  = rospy.Publisher('/bdi_manipulate_pelvis_pose_rpy',PoseStamped)
        self.pelvis_trajectory_pub = rospy.Publisher(
            "/robot_controllers/pelvis_traj_controller/command", JointTrajectory, queue_size=10
        )
        self.stateSubscriber = rospy.Subscriber(
            "/robot_controllers/pelvis_traj_controller/state", JointTrajectoryControllerState, self.stateCallbackFnc
        )
class TextSearchFrame(QDockWidget):
    '''
    A frame to find text in the Editor.
    '''
    search_result_signal = Signal(str, bool, str, int)
    ''' @ivar: A signal emitted after search_threaded was started.
        (search text, found or not, file, position in text)
        for each result a signal will be emitted.
    '''
    replace_signal = Signal(str, str, int, str)
    ''' @ivar: A signal emitted to replace string at given position.
        (search text, file, position in text, replaced by text)
    '''

    def __init__(self, tabwidget, parent=None):
        QDockWidget.__init__(self, "Find", parent)
        self.setObjectName('SearchFrame')
        self.setFeatures(QDockWidget.DockWidgetMovable | QDockWidget.DockWidgetFloatable)
        self._dockwidget = QFrame(self)
        self.vbox_layout = QVBoxLayout(self._dockwidget)
        self.layout().setContentsMargins(0, 0, 0, 0)
        self.layout().setSpacing(1)
        # frame with two rows for find and replace
        find_replace_frame = QFrame(self)
        find_replace_vbox_layout = QVBoxLayout(find_replace_frame)
        find_replace_vbox_layout.setContentsMargins(0, 0, 0, 0)
        find_replace_vbox_layout.setSpacing(1)
#        find_replace_vbox_layout.addSpacerItem(QSpacerItem(1, 1, QSizePolicy.Expanding, QSizePolicy.Expanding))
        # create frame with find row
        find_frame = self._create_find_frame()
        find_replace_vbox_layout.addWidget(find_frame)
        rplc_frame = self._create_replace_frame()
        find_replace_vbox_layout.addWidget(rplc_frame)
        # frame for find&replace and search results
        self.vbox_layout.addWidget(find_replace_frame)
        self.vbox_layout.addWidget(self._create_found_frame())
#        self.vbox_layout.addStretch(2024)
        self.setWidget(self._dockwidget)
        # intern search parameters
        self._tabwidget = tabwidget
        self.current_search_text = ''
        self.search_results = []
        self.search_results_fileset = set()
        self._search_result_index = -1
        self._search_recursive = False
        self._search_thread = None

    def _create_find_frame(self):
        find_frame = QFrame(self)
        find_hbox_layout = QHBoxLayout(find_frame)
        find_hbox_layout.setContentsMargins(0, 0, 0, 0)
        find_hbox_layout.setSpacing(1)
        self.search_field = EnchancedLineEdit(find_frame)
        self.search_field.setPlaceholderText('search text')
        self.search_field.textChanged.connect(self.on_search_text_changed)
        self.search_field.returnPressed.connect(self.on_search)
        find_hbox_layout.addWidget(self.search_field)
        self.search_result_label = QLabel(find_frame)
        self.search_result_label.setText(' ')
        find_hbox_layout.addWidget(self.search_result_label)
        self.find_button_back = QPushButton("<")
        self.find_button_back.setFixedWidth(44)
        self.find_button_back.clicked.connect(self.on_search_back)
        find_hbox_layout.addWidget(self.find_button_back)
        self.find_button = QPushButton(">")
        self.find_button.setDefault(True)
        # self.find_button.setFlat(True)
        self.find_button.setFixedWidth(44)
        self.find_button.clicked.connect(self.on_search)
        find_hbox_layout.addWidget(self.find_button)
        return find_frame

    def _create_replace_frame(self):
        # create frame with replace row
        self.rplc_frame = rplc_frame = QFrame(self)
        rplc_hbox_layout = QHBoxLayout(rplc_frame)
        rplc_hbox_layout.setContentsMargins(0, 0, 0, 0)
        rplc_hbox_layout.setSpacing(1)
        self.replace_field = EnchancedLineEdit(rplc_frame)
        self.replace_field.setPlaceholderText('replace text')
        self.replace_field.returnPressed.connect(self.on_replace)
        rplc_hbox_layout.addWidget(self.replace_field)
        self.replace_result_label = QLabel(rplc_frame)
        self.replace_result_label.setText(' ')
        rplc_hbox_layout.addWidget(self.replace_result_label)
        self.replace_button = replace_button = QPushButton("> &Replace >")
        replace_button.setFixedWidth(90)
        replace_button.clicked.connect(self.on_replace_click)
        rplc_hbox_layout.addWidget(replace_button)
        rplc_frame.setVisible(False)
        return rplc_frame

    def _create_found_frame(self):
        ff_frame = QFrame(self)
        self.found_files_vbox_layout = QVBoxLayout(ff_frame)
        self.found_files_vbox_layout.setContentsMargins(0, 0, 0, 0)
        self.recursive_search_box = QCheckBox("recursive search")
        self.found_files_vbox_layout.addWidget(self.recursive_search_box)
        self.found_files_list = QTreeWidget(ff_frame)
        self.found_files_list.setColumnCount(1)
        self.found_files_list.setFrameStyle(QFrame.StyledPanel)
        self.found_files_list.setHeaderHidden(True)
        self.found_files_list.itemActivated.connect(self.on_itemActivated)
        self.found_files_list.setStyleSheet(
            "QTreeWidget {"
            "background-color:transparent;"
            "}"
            "QTreeWidget::item {"
            "background-color:transparent;"
            "}"
            "QTreeWidget::item:selected {"
            "background-color: darkgray;"
            "}")
        self.found_files_vbox_layout.addWidget(self.found_files_list)
        self.recursive_search_box.setChecked(False)
        return ff_frame

    def keyPressEvent(self, event):
        '''
        Enable the shortcats for search and replace
        '''
        self.parent().keyPressEvent(event)

    def on_search(self):
        '''
        Initiate the new search or request a next search result.
        '''
        if self.current_search_text != self.search_field.text() or self._search_recursive != self.recursive_search_box.isChecked():
            # clear current search results
            self._reset()
            self.current_search_text = self.search_field.text()
            if self.current_search_text:
                path_text = {}
                self._wait_for_result = True
                for i in range(self._tabwidget.count()):
                    path_text[self._tabwidget.widget(i).filename] = self._tabwidget.widget(i).document().toPlainText()
                self._search_recursive = self.recursive_search_box.isChecked()
                self._search_thread = TextSearchThread(self.current_search_text, self._tabwidget.currentWidget().filename, path_text=path_text, recursive=self._search_recursive)
                self._search_thread.search_result_signal.connect(self.on_search_result)
                self._search_thread.warning_signal.connect(self.on_warning_result)
                self._search_thread.start()
        elif self.search_results:
            self._check_position()
            if self.search_results:
                if self._search_result_index + 1 >= len(self.search_results):
                    self._search_result_index = -1
                self._search_result_index += 1
                (id, search_text, found, path, index, linenr, line) = self.search_results[self._search_result_index]
                self.search_result_signal.emit(search_text, found, path, index)
                self.replace_button.setEnabled(True)
        self._update_label()

    def on_search_back(self):
        '''
        Slot to handle the search back function.
        '''
        self._check_position(False)
        if self.search_results:
            self._search_result_index -= 1
            if self._search_result_index < 0:
                self._search_result_index = len(self.search_results) - 1
            self._update_label()
            (id, search_text, found, path, index, linenr, line) = self.search_results[self._search_result_index]
            self.search_result_signal.emit(search_text, found, path, index)
            self.replace_button.setEnabled(True)

    def _check_position(self, forward=True):
        try:
            # if the position of the textCursor was changed by the user, move the search index
            cur_pos = self._tabwidget.currentWidget().textCursor().position()
            id, st, _f, pa, idx, lnr, ltxt = self.search_results[self._search_result_index]
            sear_pos = idx + len(st)
            if cur_pos != sear_pos:
                first_idx = self._get_current_index_for_current_file()
                if first_idx != -1:
                    id, st, _f, pa, idx, lnr, ltxt = self.search_results[first_idx]
                    sear_pos = idx + len(st)
                    while cur_pos > sear_pos and self._tabwidget.currentWidget().filename == pa:
                        first_idx += 1
                        id, st, _f, pa, idx, lnr, ltxt = self.search_results[first_idx]
                        sear_pos = idx + len(st)
                    self._search_result_index = first_idx
                    if forward:
                        self._search_result_index -= 1
                else:
                    self._reset(True)
        except:
            pass

    def _get_current_index_for_current_file(self):
        for index in range(len(self.search_results)):
            id, _st, _f, pa, _idx = self.search_results[index]
            if self._tabwidget.currentWidget().filename == pa:
                return index
        return -1

    def on_search_result(self, search_text, found, path, index, linenr, line):
        '''
        Slot to handle the signals for search result. This signals are forwarded used
        search_result_signal.
        '''
        if found and search_text == self.current_search_text:
            id = "%d:%s" % (index, path)
            self.search_results_fileset.add(path)
            item = (search_text, found, path, index)
            if item not in self.search_results:
                self.search_results.append((id, search_text, found, path, index, linenr, line))
            if self._wait_for_result:
                self._search_result_index += 1
                if index >= self._tabwidget.currentWidget().textCursor().position() or self._tabwidget.currentWidget().filename != path:
                    self._wait_for_result = False
                    self.search_result_signal.emit(search_text, found, path, index)
                    self.replace_button.setEnabled(True)
            pkg, rpath = package_name(os.path.dirname(path))
            itemstr = '%s [%s]' % (os.path.basename(path), pkg)
            if not self.found_files_list.findItems(itemstr, Qt.MatchExactly):
                list_item = QTreeWidgetItem(self.found_files_list)
                list_item.setText(0, itemstr)
                list_item.setToolTip(0, path)
                self.found_files_list.insertTopLevelItem(0, list_item)
                self.found_files_list.expandAll()
            for i in range(self.found_files_list.topLevelItemCount()):
                top_item = self.found_files_list.topLevelItem(i)
                if top_item.text(0) == itemstr:
                    sub_item_str = "%d: %s" % (linenr, line)
                    list_item2 = QTreeWidgetItem()
                    list_item2.setText(0, sub_item_str)
                    list_item2.setWhatsThis(0, id)
                    top_item.addChild(list_item2)
                #self.found_files_list.setVisible(len(self.search_results_fileset) > 0)
        self._update_label()

    def on_warning_result(self, text):
        rospy.logwarn(text)

    def on_replace_click(self):
        self.on_replace()
        self.on_search()

    def on_replace(self):
        '''
        Emits the replace signal, but only if currently selected text is equal to the searched one.
        '''
        if self.search_results:
            try:
                id, search_text, _found, path, index, linenr, line_text = self.search_results[self._search_result_index]
                cursor = self._tabwidget.currentWidget().textCursor()
                if cursor.selectedText() == search_text:
                    rptxt = self.replace_field.text()
                    for rindex in range(self._search_result_index + 1, len(self.search_results)):
                        iid, st, _f, pa, idx, lnr, ltxt = self.search_results[rindex]
                        if path == pa:
                            self.search_results.pop(rindex)
                            self.search_results.insert(rindex, (iid, st, _f, pa, idx + len(rptxt) - len(st), lnr, ltxt))
                        else:
                            break
                    self._remove_search_result(self._search_result_index)
                    self._search_result_index -= 1
                    self.replace_signal.emit(search_text, path, index, rptxt)
                else:
                    self.replace_button.setEnabled(False)
            except:
                import traceback
                print traceback.format_exc()
                pass

    def on_itemActivated(self, item):
        '''
        Go to the results for the selected file entry in the list.
        '''
        splits = item.whatsThis(0).split(':')
        if len(splits) == 2:
            item_index = int(splits[0])
            item_path = splits[1]
            new_search_index = -1
            tmp_index = -1
            search_index = -1
            tmp_search_text = ''
            for id, search_text, found, path, index, linenr, line_text in self.search_results:
                new_search_index += 1
                if item_path == path and item_index == index:
                    self._search_result_index = new_search_index
                    self.search_result_signal.emit(search_text, found, path, index)
                    self._update_label()

    def on_search_text_changed(self, _text):
        '''
        Clear search result if the text was changed.
        '''
        self._reset()

    def _update_label(self, clear_label=False):
        '''
        Updates the status label for search results. The info is created from search result lists.
        '''
        msg = ' '
        if self.search_results:
            count_files = len(self.search_results_fileset)
            msg = '%d/%d' % (self._search_result_index + 1, len(self.search_results))
            if count_files > 1:
                msg = '%s(%d)' % (msg, count_files)
        if self._search_thread is not None and self._search_thread.is_alive():
            msg = 'searching..%s' % msg
        elif not msg.strip() and self.current_search_text:
            msg = '0 found'
            self.current_search_text = ''
        if clear_label:
            msg = ' '
        self.search_result_label.setText(msg)
        self.find_button_back.setEnabled(len(self.search_results))
        self._select_current_item_in_box(self._search_result_index)

    def file_changed(self, path):
        '''
        Clears search results if for changed file are some search results are available
        :param path: changed file path
        :type path: str
        '''
        if path in self.search_results_fileset:
            self._reset()

    def set_replace_visible(self, value):
        self.rplc_frame.setVisible(value)
        self.raise_()
        self.activateWindow()
        if value:
            self.replace_field.setFocus()
            self.replace_field.selectAll()
            self.setWindowTitle("Find / Replace")
        else:
            self.setWindowTitle("Find")
            self.search_field.setFocus()

    def is_replace_visible(self):
        return self.rplc_frame.isVisible()

    def _reset(self, force_new_search=False):
        # clear current search results
        if self._search_thread is not None:
            self._search_thread.search_result_signal.disconnect()
            self._search_thread.stop()
            self._search_thread = None
        self.current_search_text = ''
        self.search_results = []
        self.search_results_fileset = set()
        self.found_files_list.clear()
#        self.found_files_list.setVisible(False)
        self._update_label(True)
        self._search_result_index = -1
        self.find_button_back.setEnabled(False)
        if force_new_search:
            self.on_search()

    def enable(self):
        self.setVisible(True)
#        self.show()
        self.raise_()
        self.activateWindow()
        self.search_field.setFocus()
        self.search_field.selectAll()

    def _select_current_item_in_box(self, index):
        try:
            (id, search_text, found, path, index, linenr, line) = self.search_results[index]
            for topidx in range(self.found_files_list.topLevelItemCount()):
                topitem = self.found_files_list.topLevelItem(topidx)
                for childdx in range(topitem.childCount()):
                    child = topitem.child(childdx)
                    if child.whatsThis(0) == id:
                        child.setSelected(True)
                    elif child.isSelected():
                        child.setSelected(False)
        except:
            pass

    def _remove_search_result(self, index):
        try:
            (id, search_text, found, path, index, linenr, line) = self.search_results.pop(index)
            pkg, rpath = package_name(os.path.dirname(path))
            itemstr = '%s [%s]' % (os.path.basename(path), pkg)
            found_items = self.found_files_list.findItems(itemstr, Qt.MatchExactly)
            for item in found_items:
                for chi in range(item.childCount()):
                    child = item.child(chi)
                    if child.whatsThis(0) == id:
                        item.removeChild(child)
                        break
            # delete top level item if it is now empty
            for topidx in range(self.found_files_list.topLevelItemCount()):
                if self.found_files_list.topLevelItem(topidx).childCount() == 0:
                    self.found_files_list.takeTopLevelItem(topidx)
                    break
            # create new set with files contain the search text
            new_path_set = set(path for _id, _st, _fd, path, _idx, lnr, lntxt in self.search_results)
            self.search_results_fileset = new_path_set
#            self.found_files_list.setVisible(len(self.search_results_fileset) > 0)
        except:
            import traceback
            print traceback.format_exc()
class SelectDialog(QDialog):
    '''
    This dialog creates an input mask for a string list and return selected entries.
    '''

    def __init__(self, items=list(), buttons=QDialogButtonBox.Cancel | QDialogButtonBox.Ok, exclusive=False,
                 preselect_all=False, title='', description='', icon='', parent=None, select_if_single=True,
                 checkitem1='', checkitem2=''):
        '''
        Creates an input dialog.
        @param items: a list with strings
        @type items: C{list()}
        '''
        QDialog.__init__(self, parent=parent)
        self.setObjectName(' - '.join(['SelectDialog', str(items)]))

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout.setContentsMargins(1, 1, 1, 1)

        # add filter row
        self.filter_frame = QFrame(self)
        filterLayout = QHBoxLayout(self.filter_frame)
        filterLayout.setContentsMargins(1, 1, 1, 1)
        label = QLabel("Filter:", self.filter_frame)
        self.filter_field = EnchancedLineEdit(self.filter_frame)
        filterLayout.addWidget(label)
        filterLayout.addWidget(self.filter_field)
        self.filter_field.textChanged.connect(self._on_filter_changed)
        self.verticalLayout.addWidget(self.filter_frame)

        if description:
            self.description_frame = QFrame(self)
            descriptionLayout = QHBoxLayout(self.description_frame)
#      descriptionLayout.setContentsMargins(1, 1, 1, 1)
            if icon:
                self.icon_label = QLabel(self.description_frame)
                self.icon_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
                self.icon_label.setPixmap(QPixmap(icon).scaled(30, 30, Qt.KeepAspectRatio))
                descriptionLayout.addWidget(self.icon_label)
            self.description_label = QLabel(self.description_frame)
            self.description_label.setWordWrap(True)
            self.description_label.setText(description)
            descriptionLayout.addWidget(self.description_label)
            self.verticalLayout.addWidget(self.description_frame)

        # create area for the parameter
        self.content = MainBox(self)
        if items:
            self.scroll_area = QScrollArea(self)
            self.scroll_area.setFocusPolicy(Qt.NoFocus)
            self.scroll_area.setObjectName("scroll_area")
            self.scroll_area.setWidgetResizable(True)
            self.scroll_area.setWidget(self.content)
            self.verticalLayout.addWidget(self.scroll_area)

        self.checkitem1 = checkitem1
        self.checkitem1_result = False
        self.checkitem2 = checkitem2
        self.checkitem2_result = False

        # add select all option
        if not exclusive and items:
            self._ignore_next_toggle = False
            self.select_all_checkbox = QCheckBox('all entries')
            self.select_all_checkbox.setTristate(True)
            self.select_all_checkbox.stateChanged.connect(self._on_select_all_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.select_all_checkbox)
            self.content.toggled.connect(self._on_main_toggle)
        if self.checkitem1:
            self.checkitem1_checkbox = QCheckBox(self.checkitem1)
            self.checkitem1_checkbox.stateChanged.connect(self._on_select_checkitem1_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.checkitem1_checkbox)
        if self.checkitem2:
            self.checkitem2_checkbox = QCheckBox(self.checkitem2)
            self.checkitem2_checkbox.stateChanged.connect(self._on_select_checkitem2_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.checkitem2_checkbox)
        if not items:
            spacerItem = QSpacerItem(1, 1, QSizePolicy.Expanding, QSizePolicy.Expanding)
            self.verticalLayout.addItem(spacerItem)

        # create buttons
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setObjectName("buttonBox")
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(buttons)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.verticalLayout.addWidget(self.buttonBox)

        # set the input fields
        if items:
            self.content.createFieldsFromValues(items, exclusive)
            if (select_if_single and len(items) == 1) or preselect_all:
                self.select_all_checkbox.setCheckState(Qt.Checked)

        if not items or len(items) < 7:
            self.filter_frame.setVisible(False)
#    print '=============== create', self.objectName()
#
#  def __del__(self):
#    print "************ destroy", self.objectName()

    def _on_main_toggle(self, state):
        self._ignore_next_toggle = state != self.select_all_checkbox.checkState()
        self.select_all_checkbox.setCheckState(state)

    def _on_select_all_checkbox_stateChanged(self, state):
        if not self._ignore_next_toggle:
            self.content.setState(state)
        self._ignore_next_toggle = False

    def _on_select_checkitem1_checkbox_stateChanged(self, state):
        if state == Qt.Checked:
            self.checkitem1_result = True
        elif state == Qt.Unchecked:
            self.checkitem1_result = False

    def _on_select_checkitem2_checkbox_stateChanged(self, state):
        if state == Qt.Checked:
            self.checkitem2_result = True
        elif state == Qt.Unchecked:
            self.checkitem2_result = False

    def _on_filter_changed(self):
        self.content.filter(self.filter_field.text())

    def getSelected(self):
        return self.content.getSelected()

    @staticmethod
    def getValue(title, description='', items=list(), exclusive=False, preselect_all=False, icon='', parent=None, select_if_single=True, checkitem1='', checkitem2=''):
        selectDia = SelectDialog(items, exclusive=exclusive, preselect_all=preselect_all, description=description, icon=icon, parent=parent, select_if_single=select_if_single, checkitem1=checkitem1, checkitem2=checkitem2)
        selectDia.setWindowTitle(title)
        selectDia.resize(480, 256)
        if selectDia.exec_():
            if selectDia.checkitem2:
                return selectDia.getSelected(), True, selectDia.checkitem1_result, selectDia.checkitem2_result
            if selectDia.checkitem1:
                return selectDia.getSelected(), True, selectDia.checkitem1_result
            return selectDia.getSelected(), True
        if selectDia.checkitem2:
            return list(), False, False, False
        if selectDia.checkitem1:
            return list(), False, False
        return list(), False


# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# %%%%%%%%%%%%%%%%%% close handling                        %%%%%%%%%%%%%%%%%%%%%
# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    def accept(self):
        self.setResult(QDialog.Accepted)
        self.hide()

    def reject(self):
        self.setResult(QDialog.Rejected)
        self.hide()

    def hideEvent(self, event):
        self.close()

    def closeEvent(self, event):
        '''
        Test the open files for changes and save this if needed.
        '''
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        QDialog.closeEvent(self, event)
class CapabilityControlWidget(QFrame):
    '''
    The control widget contains buttons for control a capability. Currently this
    are C{On} and C{Off} buttons. Additionally, the state of the capability is
    color coded.
    '''

    start_nodes_signal = Signal(str, str, list)
    '''@ivar: the signal is emitted to start on host(described by masteruri) the nodes described in the list, Parameter(masteruri, config, nodes).'''

    stop_nodes_signal = Signal(str, list)
    '''@ivar: the signal is emitted to stop on masteruri the nodes described in the list.'''

    def __init__(self, masteruri, cfg, ns, nodes, parent=None):
        QFrame.__init__(self, parent)
        self._masteruri = masteruri
        self._nodes = {cfg: {ns: nodes}}
        frame_layout = QVBoxLayout(self)
        frame_layout.setContentsMargins(0, 0, 0, 0)
        # create frame for warning label
        self.warning_frame = warning_frame = QFrame(self)
        warning_layout = QHBoxLayout(warning_frame)
        warning_layout.setContentsMargins(0, 0, 0, 0)
        warning_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.warning_label = QLabel()
        icon = QIcon(':/icons/crystal_clear_warning.png')
        self.warning_label.setPixmap(icon.pixmap(QSize(40, 40)))
        self.warning_label.setToolTip('Multiple configuration for same node found!\nA first one will be selected for the start a node!')
        warning_layout.addWidget(self.warning_label)
        warning_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        frame_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        frame_layout.addWidget(warning_frame)
        # create frame for start/stop buttons
        buttons_frame = QFrame()
        buttons_layout = QHBoxLayout(buttons_frame)
        buttons_layout.setContentsMargins(0, 0, 0, 0)
        buttons_layout.addItem(QSpacerItem(20, 20))
        self.on_button = QPushButton()
        self.on_button.setFlat(False)
        self.on_button.setText("On")
        self.on_button.clicked.connect(self.on_on_clicked)
        buttons_layout.addWidget(self.on_button)

        self.off_button = QPushButton()
        self.off_button.setFlat(True)
        self.off_button.setText("Off")
        self.off_button.clicked.connect(self.on_off_clicked)
        buttons_layout.addWidget(self.off_button)
        buttons_layout.addItem(QSpacerItem(20, 20))
        frame_layout.addWidget(buttons_frame)
        frame_layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Expanding))
        self.warning_frame.setVisible(False)

    def hasConfigs(self):
        '''
        @return: True, if a configurations for this widget are available.
        @rtype: bool
        '''
        return len(self._nodes) > 0

    def nodes(self, cfg=''):
        '''
        @return: the list with nodes required by this capability. The nodes are
        defined by ROS full name.
        @rtype: C{[str]}
        '''
        try:
            if cfg:
                return [n for l in self._nodes[cfg].itervalues() for n in l]
            else:
                return [n for c in self._nodes.itervalues() for l in c.itervalues() for n in l]
        except:
            return []

    def setNodeState(self, running_nodes, stopped_nodes, error_nodes):
        '''
        Sets the state of this capability.
        @param running_nodes: a list with running nodes.
        @type running_nodes: C{[str]}
        @param stopped_nodes: a list with not running nodes.
        @type stopped_nodes: C{[str]}
        @param error_nodes: a list with nodes having a problem.
        @type error_nodes: C{[str]}
        '''
        self.setAutoFillBackground(True)
        self.setBackgroundRole(QPalette.Base)
        palette = QPalette()
        if error_nodes:
            brush = QBrush(QColor(255, 100, 0))
        elif running_nodes and stopped_nodes:
            brush = QBrush(QColor(140, 185, 255))  # 30, 50, 255
        elif running_nodes:
            self.on_button.setFlat(True)
            self.off_button.setFlat(False)
            brush = QBrush(QColor(59, 223, 18))  # 59, 223, 18
        else:
            brush = QBrush(QColor(255, 255, 255))
            self.on_button.setFlat(False)
            self.off_button.setFlat(True)
        palette.setBrush(QPalette.Active, QPalette.Base, brush)
        brush.setStyle(Qt.SolidPattern)
        palette.setBrush(QPalette.Inactive, QPalette.Base, brush)
        self.setPalette(palette)

    def removeCfg(self, cfg):
        try:
            del self._nodes[cfg]
        except:
            pass

    def updateNodes(self, cfg, ns, nodes):
        self._nodes[cfg] = {ns: nodes}
        test_nodes = self.nodes()
        self.warning_frame.setVisible(len(test_nodes) != len(set(test_nodes)))

    def on_on_clicked(self):
        started = set()  # do not start nodes multiple times
        for c in self._nodes.iterkeys():
            node2start = set(self.nodes(c)) - started
            self.start_nodes_signal.emit(self._masteruri, c, list(node2start))
            started.update(node2start)
        self.on_button.setFlat(True)
        self.off_button.setFlat(False)

    def on_off_clicked(self):
        self.stop_nodes_signal.emit(self._masteruri, self.nodes())
        self.on_button.setFlat(False)
        self.off_button.setFlat(True)
class ParamWidget(QWidget):
    _TITLE_PLUGIN = 'Dynamic Reconfigure'

    # To be connected to PluginContainerWidget
    sig_sysmsg = Signal(str)
    sig_sysprogress = Signal(str)

    # To make selections from CLA
    sig_selected = Signal(str)

    def __init__(self, context, node=None):
        """
        This class is intended to be called by rqt plugin framework class.
        Currently (12/12/2012) the whole widget is splitted into 2 panes:
        one on left allows you to choose the node(s) you work on. Right side
        pane lets you work with the parameters associated with the node(s) you
        select on the left.

        (12/27/2012) Despite the pkg name is changed to rqt_reconfigure to
        reflect the available functionality, file & class names remain
        'param', expecting all the parameters will become handle-able.
        """

        super(ParamWidget, self).__init__()
        self.setObjectName(self._TITLE_PLUGIN)
        self.setWindowTitle(self._TITLE_PLUGIN)

        rp = rospkg.RosPack()

        #TODO: .ui file needs to replace the GUI components declaration
        #            below. For unknown reason, referring to another .ui files
        #            from a .ui that is used in this class failed. So for now,
        #            I decided not use .ui in this class.
        #            If someone can tackle this I'd appreciate.
        _hlayout_top = QHBoxLayout(self)
        _hlayout_top.setContentsMargins(QMargins(0, 0, 0, 0))
        self._splitter = QSplitter(self)
        _hlayout_top.addWidget(self._splitter)

        _vlayout_nodesel_widget = QWidget()
        _vlayout_nodesel_side = QVBoxLayout()
        _hlayout_filter_widget = QWidget(self)
        _hlayout_filter = QHBoxLayout()
        self._text_filter = TextFilter()
        self.filter_lineedit = TextFilterWidget(self._text_filter, rp)
        self.filterkey_label = QLabel("&Filter key:")
        self.filterkey_label.setBuddy(self.filter_lineedit)
        _hlayout_filter.addWidget(self.filterkey_label)
        _hlayout_filter.addWidget(self.filter_lineedit)
        _hlayout_filter_widget.setLayout(_hlayout_filter)
        self._nodesel_widget = NodeSelectorWidget(self, rp, self.sig_sysmsg)
        _vlayout_nodesel_side.addWidget(_hlayout_filter_widget)
        _vlayout_nodesel_side.addWidget(self._nodesel_widget)
        _vlayout_nodesel_side.setSpacing(1)
        _vlayout_nodesel_widget.setLayout(_vlayout_nodesel_side)

        reconf_widget = ParameditWidget(rp)

        self._splitter.insertWidget(0, _vlayout_nodesel_widget)
        self._splitter.insertWidget(1, reconf_widget)
        # 1st column, _vlayout_nodesel_widget, to minimize width.
        # 2nd col to keep the possible max width.
        self._splitter.setStretchFactor(0, 0)
        self._splitter.setStretchFactor(1, 1)

        # Signal from paramedit widget to node selector widget.
        reconf_widget.sig_node_disabled_selected.connect(
                                       self._nodesel_widget.node_deselected)
        # Pass name of node to editor widget
        self._nodesel_widget.sig_node_selected.connect(
                                                     reconf_widget.show_reconf)

        if not node:
            title = self._TITLE_PLUGIN
        else:
            title = self._TITLE_PLUGIN + ' %s' % node
        self.setObjectName(title)

        #Connect filter signal-slots.
        self._text_filter.filter_changed_signal.connect(
                                            self._filter_key_changed)

        # Open any clients indicated from command line
        self.sig_selected.connect(self._nodesel_widget.node_selected)
        for rn in [rospy.resolve_name(c) for c in context.argv()]:
            if rn in self._nodesel_widget.get_paramitems():
                self.sig_selected.emit(rn)
            else:
                rospy.logwarn('Could not find a dynamic reconfigure client named \'%s\'', str(rn))

    def shutdown(self):
        #TODO: Needs implemented. Trigger dynamic_reconfigure to unlatch
        #            subscriber.
        pass

    def save_settings(self, plugin_settings, instance_settings):
        instance_settings.set_value('splitter', self._splitter.saveState())

    def restore_settings(self, plugin_settings, instance_settings):
        if instance_settings.contains('splitter'):
            self._splitter.restoreState(instance_settings.value('splitter'))
        else:
            self._splitter.setSizes([100, 100, 200])

    def get_filter_text(self):
        """
        :rtype: QString
        """
        return self.filter_lineedit.text()

    def _filter_key_changed(self):
        self._nodesel_widget.set_filter(self._text_filter)

    #TODO: This method should be integrated into common architecture. I just
    # can't think of how to do so within current design.
    def emit_sysmsg(self, msg_str):
        self.sig_sysmsg.emit(msg_str)
Exemple #49
0
class PingGUI(Plugin):
    def __init__(self, context):
        super(PingGUI, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName("PingGUI")
        self.msg = None
        # Create a container widget and give it a layout
        self._container = QWidget()
        self._layout = QVBoxLayout()
        self._container.setLayout(self._layout)
        self._label = QLabel("xx ms latency")
        p = self._label.palette()
        p.setColor(self._label.backgroundRole(), Qt.red)
        self._label.setPalette(p)
        self._layout.addWidget(self._label)
        self.set_bg_color(100, 100, 100)

        rospy.Subscriber("/ping/delay", Float64, self.ping_cb)
        context.add_widget(self._container)
        self._update_plot_timer = QTimer(self)
        self._update_plot_timer.timeout.connect(self.update_gui)
        self._update_plot_timer.start(1)

    def update_gui(self):
        if not self.msg:
            return
        msg = self.msg
        # msec
        # 100 -> green, 1000 -> red
        # normalize within 1000 ~ 100
        orig_latency = msg.data
        msg_data = orig_latency
        if msg.data > 1000:
            msg_data = 1000
        elif msg.data < 100:
            msg_data = 100
        ratio = (msg_data - 100) / (1000 - 100)
        color_r = ratio * 255.0
        color_g = (1 - ratio) * 255.0
        # devnull = open(os.devnull, "w")
        # with RedirectStdStreams(stdout=devnull, stderr=devnull):
        self.set_bg_color(color_r, color_g, 0)
        self._label.setText("%d ms latency" % (orig_latency))

    def set_bg_color(self, r, g, b):
        self._label.setStyleSheet(
            "QLabel { display: block; background-color: rgba(%d, %d, %d, 255); text-align: center; font-size: 30px;}"
            % (r, g, b)
        )

    def ping_cb(self, msg):
        self.msg = msg

    def shutdown_plugin(self):
        pass

    def save_settings(self, plugin_settings, instance_settings):
        pass

    def restore_settings(self, plugin_settings, instance_settings):
        pass
    def __init__(self, items=list(), buttons=QDialogButtonBox.Cancel | QDialogButtonBox.Ok, exclusive=False,
                 preselect_all=False, title='', description='', icon='', parent=None, select_if_single=True,
                 checkitem1='', checkitem2=''):
        '''
        Creates an input dialog.
        @param items: a list with strings
        @type items: C{list()}
        '''
        QDialog.__init__(self, parent=parent)
        self.setObjectName(' - '.join(['SelectDialog', str(items)]))

        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout.setContentsMargins(1, 1, 1, 1)

        # add filter row
        self.filter_frame = QFrame(self)
        filterLayout = QHBoxLayout(self.filter_frame)
        filterLayout.setContentsMargins(1, 1, 1, 1)
        label = QLabel("Filter:", self.filter_frame)
        self.filter_field = EnchancedLineEdit(self.filter_frame)
        filterLayout.addWidget(label)
        filterLayout.addWidget(self.filter_field)
        self.filter_field.textChanged.connect(self._on_filter_changed)
        self.verticalLayout.addWidget(self.filter_frame)

        if description:
            self.description_frame = QFrame(self)
            descriptionLayout = QHBoxLayout(self.description_frame)
#      descriptionLayout.setContentsMargins(1, 1, 1, 1)
            if icon:
                self.icon_label = QLabel(self.description_frame)
                self.icon_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
                self.icon_label.setPixmap(QPixmap(icon).scaled(30, 30, Qt.KeepAspectRatio))
                descriptionLayout.addWidget(self.icon_label)
            self.description_label = QLabel(self.description_frame)
            self.description_label.setWordWrap(True)
            self.description_label.setText(description)
            descriptionLayout.addWidget(self.description_label)
            self.verticalLayout.addWidget(self.description_frame)

        # create area for the parameter
        self.content = MainBox(self)
        if items:
            self.scroll_area = QScrollArea(self)
            self.scroll_area.setFocusPolicy(Qt.NoFocus)
            self.scroll_area.setObjectName("scroll_area")
            self.scroll_area.setWidgetResizable(True)
            self.scroll_area.setWidget(self.content)
            self.verticalLayout.addWidget(self.scroll_area)

        self.checkitem1 = checkitem1
        self.checkitem1_result = False
        self.checkitem2 = checkitem2
        self.checkitem2_result = False

        # add select all option
        if not exclusive and items:
            self._ignore_next_toggle = False
            self.select_all_checkbox = QCheckBox('all entries')
            self.select_all_checkbox.setTristate(True)
            self.select_all_checkbox.stateChanged.connect(self._on_select_all_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.select_all_checkbox)
            self.content.toggled.connect(self._on_main_toggle)
        if self.checkitem1:
            self.checkitem1_checkbox = QCheckBox(self.checkitem1)
            self.checkitem1_checkbox.stateChanged.connect(self._on_select_checkitem1_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.checkitem1_checkbox)
        if self.checkitem2:
            self.checkitem2_checkbox = QCheckBox(self.checkitem2)
            self.checkitem2_checkbox.stateChanged.connect(self._on_select_checkitem2_checkbox_stateChanged)
            self.verticalLayout.addWidget(self.checkitem2_checkbox)
        if not items:
            spacerItem = QSpacerItem(1, 1, QSizePolicy.Expanding, QSizePolicy.Expanding)
            self.verticalLayout.addItem(spacerItem)

        # create buttons
        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setObjectName("buttonBox")
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(buttons)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.verticalLayout.addWidget(self.buttonBox)

        # set the input fields
        if items:
            self.content.createFieldsFromValues(items, exclusive)
            if (select_if_single and len(items) == 1) or preselect_all:
                self.select_all_checkbox.setCheckState(Qt.Checked)

        if not items or len(items) < 7:
            self.filter_frame.setVisible(False)
class ButtonSetPopupSelector(QDialog):
    '''
    An interactive dialog that displays successive sets of
    buttons. When each set is displayed, user may ask for the
    next available set, the previous. already seen set, or the
    user may accept the currently displayed set. A cancel is 
    available as well. 
    
    The call and return protocol is as follows:

      - The caller creates a fresh dialog instance of this class,
        passing an iterator. The iterator's next() method returns 
        an array of ButtonProgram instances each time it is called. (When the
        iterator is exhausted, the user is able to use a 'Previous'
        button to view the previously seen sets again).
      - The caller invokes the exec_() method on the dialog instance.
      - The exec_() method returns:
          
              - -1, if the iterator yielded no button label arrays at all.
              - 0, if the user canceled, and 
              - 1 if the user accepted one of the sets.

      - If the exec_() method returned 1, the caller may obtain an array with the
        ButtonProgram instances of the currently showing (and therefore accepted) buttons.
        The array is obtained from the dialog instance via method getCurrentlyShowingSetLabels(self). 
    '''
    #------------------------------------------------------   Public  Methods ---------------------------
    
    def __init__(self, buttonProgramArrayIterator):
        
        super(ButtonSetPopupSelector, self).__init__();

        self.setStyleSheet(SpeakEasyGUI.stylesheetAppBG);
        
        self.programButtonDict = {};
        self.buttonProgramArrayIt = buttonProgramArrayIterator;
        self.buttonProgramArrays = []; # saved ButtonProgram arrays
        self.shownLabelArrays = [];
        self.currentlyShowingSetIndex = None;
        self.rootLayout = None;
        
        self.cancelButton = QPushButton("Cancel");
        self.cancelButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet);
        self.cancelButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT);
        #self.cancelButton.clicked.connect(partial(QDialog.done, self, 0));
        self.cancelButton.clicked.connect(self.clickedCancelButton);
        
        self.OKButton = QPushButton("Pick this One");
        self.OKButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet);
        self.OKButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT);
        self.OKButton.clicked.connect(self.clickedOKButton);
        
        self.currentNextPrevDirection = NextPrev.NEXT;

        self.nextButton = QPushButton("Next");
        self.nextButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet);
        self.nextButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT);
        self.nextButton.clicked.connect(self.clickedNextButton);

        self.prevButton = QPushButton("Previous");
        self.prevButton.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet);
        self.prevButton.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT);
        self.prevButton.clicked.connect(self.clickedPrevButton);

        self.setNextPrevButtonsEnabledness();
        
        self.endOfSetsLabel = QLabel("<b>No more button sets.</b>")
        self.noSetsLabel = QLabel("<b>No button sets available.</b>")

        self.noAvailableSets = False;
        self.offerNewButtonSet();
    
    
    def exec_(self):
        '''
        If the prior initialization revealed that the caller does not
        deliver any sets of button labels at all, then return -1, without
        displaying any dialog.
        @return: -1 if no button sets available. 1 if user accepted one of the button
                 label sets as the one they want, or 0, if the user cancelled.
        @rtype: int
        '''
        if self.noAvailableSets:
            return -1;
        return super(ButtonSetPopupSelector, self).exec_();

    def getCurrentlyShowingSet(self):
        '''
        Returns an array of ButtonProgram instances that are currently showing on
        the dialog, or were showing when the user clicked OK.
        @return: Array of ButtonProgram instances.
        @rtype: [ButtonProgram]
        '''
        return self.buttonProgramArrays[self.currentlyShowingSetIndex];

    def getCurrentlyShowingSetLabels(self):
        '''
        Returns an array of labels of buttons that are currently showing on
        the dialog, or were showing when the user clicked OK.
        @return: Array of labels.
        @rtype: [string]
        '''
        allLabels = [];
        for buttonProgram in self.buttonProgramArrays[self.currentlyShowingSetIndex]:
            allLabels.append(buttonProgram.getLabel()); 
        return allLabels;



    #------------------------------------------------------   Private  Methods ---------------------------
    
    def offerNewButtonSet(self):
        '''
        Responsible for displaying the next, or previous set of buttons.
        During successive calls to this method, the method obtains new 
        button label sets from the caller's iterator until the iterator
        is exhausted. The sets are collected in <code>self.shownLabelArrays</code>.
        The method is also responsible for showing previously shown sets again. 
        The direction is controlled by the handlers of the Previous and Next buttons.
        They set instance variable <code>currentNextPrevDirection</code>. 
        '''

        # Make sure the 'No more button sets in this direction" 
        # message gets deleted:
        self.endOfSetsLabel.hide();
        self.enableActionButton(self.OKButton);

        # Want to display a previously displayed button set?        
        if self.currentNextPrevDirection == NextPrev.PREVIOUS:
            # Are we showing the first set, i.e. is there no set
            # before the current one?
            if self.currentlyShowingSetIndex == 0:
                # Show the 'nothing before this one' label,
                # and switch directions:
                self.flipNextPrevDirection();
                return;
            self.currentlyShowingSetIndex -= 1;
            self.buildButtonSet(self.getCurrentlyShowingSetLabels());
            #***************
            self.setButtonSetTitleInWindow(self.currentlyShowingSetIndex + 1);
            #***************
            self.setNextPrevButtonsEnabledness();
            return;
        
        # Wants next button set. Is there one we haven't shown yet?:
        try:
            # Get next set of ButtonProgram instances from caller:
            buttonProgramArray = self.buttonProgramArrayIt.next();
            # Save this ButtonProgram instance:
            self.buttonProgramArrays.append(buttonProgramArray);
            
            # From the ButtonProgram objects array, create an
            # array of just the button labels:
            buttonLabelArray = [];
            for buttonProgram in buttonProgramArray:
                buttonLabelArray.append(buttonProgram.getLabel());
            
            # If this is the very first time we pull a button set
            # from the caller, then our current index will be None
            # from the initialization. We use that to check for 
            # the case that the caller has no sets at all to feed
            # out. Since we didn't bomb with StopIteration, we know
            # that there is at least one available button set: 
            if self.currentlyShowingSetIndex is None:
                self.currentlyShowingSetIndex = -1;
                
            # Save that list of button names:
            self.shownLabelArrays.append(buttonLabelArray);
            self.currentlyShowingSetIndex += 1;
            #**********
            self.setButtonSetTitleInWindow(self.currentlyShowingSetIndex + 1);
            #**********
            self.buildButtonSet(buttonLabelArray);
            self.setNextPrevButtonsEnabledness();
            return;
        except StopIteration:
            # If we fell through the very first time, there is no
            # button set available at all:
            if self.currentlyShowingSetIndex is None:
                self.terminateWithWarning();
                return;
            # No more button sets available from caller's iterator:
            self.currentlyShowingSetIndex += 1;
            #**********
            self.setButtonSetTitleInWindow(self.currentlyShowingSetIndex + 1);
            #**********
        
        if self.currentlyShowingSetIndex >= len(self.shownLabelArrays):
            # Neither are there more new sets, nor are we going
            # through the already shown sets going forward a second
            # time. So reverse direction to go backwards through the
            # the already shown sets:
            self.setButtonSetTitleInWindow(-1)
            self.flipNextPrevDirection();
            return;

        self.buildButtonSet(self.getCurrentlyShowingSetLabels());
        self.setNextPrevButtonsEnabledness();

        return;
        
    def setButtonSetTitleInWindow(self, buttonSetIndex):
        '''
        Given a button set number, displays a help text in the 'pick button set' dialog.
        @param buttonSetIndex: number of button set (1-based by convention, but 0 is legal).
        set to -1 if wish to indicate absence of a relevant set. Will show as 'Showing button set --'.
        @type buttonSetIndex: int
        '''
        if buttonSetIndex > -1:
            self.setWindowTitle('Showing button set %d' % buttonSetIndex);
        else:
            self.setWindowTitle('Showing button set --');
        
    def flipNextPrevDirection(self):
        '''
        Called when no more button label sets are available
        either in the next, or previous direction.
        '''

        self.clearDialogPane();
        
        self.rootLayout.addWidget(self.endOfSetsLabel);
        # Show the 'End of sets' label, and 
        # de-activate the OK button:
        self.endOfSetsLabel.show();
        self.disableActionButton(self.OKButton);
        
        if (self.currentNextPrevDirection == NextPrev.PREVIOUS):
            self.currentNextPrevDirection = NextPrev.NEXT;
            self.currentlyShowingSetIndex = -1;
        else:
            self.currentNextPrevDirection = NextPrev.PREVIOUS;
            self.currentlyShowingSetIndex = len(self.shownLabelArrays);
            
        self.setNextPrevButtonsEnabledness();
        self.addChoiceButtons(self.rootLayout);
        self.setLayout(self.rootLayout);

    def clearDialogPane(self):
        '''
        Cleans out the dialog's layout. Does not destroy
        the control buttons (Next, Previous, Cancel, and OK),
        but does trigger deletion of all the button objects
        in the button grid. Attempts to None out references
        to UI widgets to enable garbage collection.
        '''
        if self.rootLayout is None:
            return;
        
        self.rootLayout.removeWidget(self.cancelButton);
        self.rootLayout.removeWidget(self.OKButton);
        self.rootLayout.removeWidget(self.nextButton);
        self.rootLayout.removeWidget(self.prevButton);
        self.rootLayout.removeItem(self.buttonGridLayout);

        self.buttonGritLayout = None;
        
        for buttonObj in self.programButtonDict.values():
            if buttonObj is not None:
                buttonObj.hide();
                buttonObj.deleteLater()

        for key in self.programButtonDict.keys():
            self.programButtonDict[key] = None;

        # Set this dialog's layout to the empty layout:
        self.setLayout(self.rootLayout);

    def buildButtonSet(self, buttonLabelArray):
        '''
        Constructs one set of buttons, based on passed in 
        button labels.
        
        @param buttonLabelArray: Array of button labels.
        @type buttonLabelArray: [string]
        '''

        # If we never made the root layout, make it now:
        if self.rootLayout is None:
            self.rootLayout = QVBoxLayout();
        else:
            # A previous button set is being displayed,
            # Empty out the rootLayout:
            self.clearDialogPane();
            
        # Get a layout filled with the button objects
        # in the proper styling. Also get a dictionary
        # mapping button labels to button objects:
        
        (self.buttonGridLayout, self.programButtonDict) =\
            SpeakEasyGUI.buildButtonGrid(buttonLabelArray,
                                         SpeakEasyGUI.NUM_OF_PROGRAM_BUTTON_COLUMNS);
    
        for buttonObj in self.programButtonDict.values():
            buttonObj.setStyleSheet(SpeakEasyGUI.programButtonStylesheet);
            buttonObj.setMinimumHeight(SpeakEasyGUI.BUTTON_MIN_HEIGHT);

        # Place the grid into a V-layout, and add
        # the next/previous, cancel, and OK buttons;
        self.rootLayout.addLayout(self.buttonGridLayout);
        self.addChoiceButtons(self.rootLayout);
                                                
        # Set the popup window's layout to the button grid
        # plus choice button combo:
        self.setLayout(self.rootLayout);
        
    def addChoiceButtons(self, layout):
        '''
        Appends the existing Next/Previous/Cancel/OK buttons
        into the passed-in layout.
        @param layout:
        '''
        choiceButtonRowLayout = QHBoxLayout();
        choiceButtonRowLayout.addWidget(self.nextButton);
        choiceButtonRowLayout.addWidget(self.prevButton);
        choiceButtonRowLayout.addWidget(self.cancelButton);
        choiceButtonRowLayout.addWidget(self.OKButton);
        layout.addLayout(choiceButtonRowLayout);

    def setNextPrevButtonsEnabledness(self):
        '''
        Examines the instance variables <code>shownLabelArrays</code>
        and </code>currentlyShowingSetIndex</code> to determine whether
        the Next or Previous buttons should be enabled. Acts on the result.
        '''
        if self.currentlyShowingSetIndex >= len(self.shownLabelArrays):
            # Can only go backwards:
            self.disableActionButton(self.nextButton);
            self.enableActionButton(self.prevButton);
        elif self.currentlyShowingSetIndex <= 0:
            # Can only go forward:
            self.enableActionButton(self.nextButton);
            self.disableActionButton(self.prevButton);
        else:
            self.enableActionButton(self.nextButton);
            self.enableActionButton(self.prevButton);

    def enableActionButton(self, buttonObj):
        buttonObj.setEnabled(True)
        buttonObj.setStyleSheet(SpeakEasyGUI.recorderButtonStylesheet);

    def disableActionButton(self, buttonObj):
        buttonObj.setEnabled(False)
        buttonObj.setStyleSheet(SpeakEasyGUI.recorderButtonDisabledStylesheet);

    def clickedNextButton(self):
        '''
        Handler for Next button clicks. Triggers show of next
        button set in order.
        '''
        if self.currentNextPrevDirection == NextPrev.PREVIOUS:
            self.currentNextPrevDirection = NextPrev.NEXT;
        self.offerNewButtonSet();
    
    def clickedPrevButton(self):
        '''
        Handler for Next button clicks. Triggers show of previous
        button set in order.
        '''
        if self.currentNextPrevDirection == NextPrev.NEXT:
            self.currentNextPrevDirection = NextPrev.PREVIOUS;
        self.offerNewButtonSet();

    def clickedCancelButton(self):
        self.clearDialogPane();
        self.done(0);

    def clickedOKButton(self):
        self.clearDialogPane();
        self.done(1);

    def terminateWithWarning(self):
        '''
        Called when no button sets are available from the caller at all.
        Records this event in instance variable <code>noAvailableSets</code>,
        and returns.
        '''
        # No buttons at all:
        self.clearDialogPane();
        self.noAvailableSets = True;
class BDIPelvisPoseWidget(QObject):
    updateStateSignal = Signal(object)

    def __init__(self, context):
        # super(BDIPelvisPoseWidget, self).__init__(context)
        # self.setObjectName('BDIPelvisPoseWidget')
        super(BDIPelvisPoseWidget, self).__init__()
        self.name = "BDIPelvisPoseWidget"

        self.updateStateSignal.connect(self.on_updateState)

        # self._widget = QWidget()
        self._widget = context
        vbox = QVBoxLayout()

        self.forward_position = 0.0
        self.lateral_position = 0.0
        self.height_position = 0.91
        self.roll_position = 0.0
        self.pitch_position = 0.0
        self.yaw_position = 0.0

        self.currentForward = 0.0
        self.currentLateral = 0.0
        self.currentHeight = 0.91
        self.currentRoll = 0.0
        self.currentPitch = 0.0
        self.currentYaw = 0.0
        # Define checkboxes
        vbox = QVBoxLayout()
        label = QLabel()
        label.setText("BDI Pelvis Height (Manipulate Mode Only)")  # todo - connect controller mode
        vbox.addWidget(label)

        self.enable_checkbox = QCheckBox("Enable")
        self.enable_checkbox.stateChanged.connect(self.on_enable_check)
        vbox.addWidget(self.enable_checkbox)

        self.snap_to_current_button = QPushButton("Snap to Current")
        self.snap_to_current_button.pressed.connect(self.on_snapCurrentPressed)
        vbox.addWidget(self.snap_to_current_button)

        self.roll_slider = QSlider(Qt.Horizontal)
        self.roll_label = QLabel()
        self.roll_label.setText("Roll")
        vbox.addWidget(self.roll_label)

        self.roll_slider.setRange(int(-100), int(101))
        self.roll_slider.setValue(int(0))
        self.roll_slider.setSingleStep((200) / 50)
        self.roll_slider.setTickInterval(25)
        self.roll_slider.valueChanged.connect(self.on_rollSliderMoved)
        vbox.addWidget(self.roll_slider)

        self.roll_progress_bar = QProgressBar()
        self.roll_progress_bar.setRange(int(-100), int(101))
        self.roll_progress_bar.setValue((6.0 / math.pi) * self.currentRoll * 100)
        self.roll_progress_bar.setFormat("%.6f" % self.currentRoll)
        vbox.addWidget(self.roll_progress_bar)

        self.pitch_slider = QSlider(Qt.Horizontal)
        self.pitch_label = QLabel()
        self.pitch_label.setText("Pitch")
        vbox.addWidget(self.pitch_label)

        self.pitch_slider.setRange(int(-100), int(101))
        self.pitch_slider.setValue(int(0))
        self.pitch_slider.setSingleStep((200) / 50)
        self.pitch_slider.setTickInterval(25)
        self.pitch_slider.valueChanged.connect(self.on_pitchSliderMoved)
        vbox.addWidget(self.pitch_slider)

        self.pitch_progress_bar = QProgressBar()
        self.pitch_progress_bar.setRange(int(-100), int(101))
        self.pitch_progress_bar.setValue((6.0 / math.pi) * self.currentPitch * 100)
        self.pitch_progress_bar.setFormat("%.6f" % self.currentPitch)
        vbox.addWidget(self.pitch_progress_bar)

        self.yaw_slider = QSlider(Qt.Horizontal)
        self.yaw_label = QLabel()
        self.yaw_label.setText("Yaw")
        vbox.addWidget(self.yaw_label)

        self.yaw_slider.setRange(int(-100), int(101))
        self.yaw_slider.setValue(int(0))
        self.yaw_slider.setSingleStep((200) / 50)
        self.yaw_slider.setTickInterval(25)
        self.yaw_slider.valueChanged.connect(self.on_yawSliderMoved)
        vbox.addWidget(self.yaw_slider)

        self.yaw_progress_bar = QProgressBar()
        self.yaw_progress_bar.setRange(int(-100), int(101))
        self.yaw_progress_bar.setValue((4.0 / math.pi) * self.currentYaw * 100)
        self.yaw_progress_bar.setFormat("%.6f" % self.currentYaw)
        vbox.addWidget(self.yaw_progress_bar)

        self.forward_label = QLabel()
        self.forward_label.setText("Forward")
        vbox.addWidget(self.forward_label)

        widget = QWidget()
        hbox = QHBoxLayout()
        hbox.addStretch()
        self.forward_slider = QSlider(Qt.Vertical)
        # self.forward_slider.setText("Height")
        self.forward_slider.setRange(int(-101), int(100))
        self.forward_slider.setValue(int(0))
        self.forward_slider.setSingleStep(1)
        self.forward_slider.setTickInterval(10)
        self.forward_slider.valueChanged.connect(self.on_forwardSliderMoved)
        hbox.addWidget(self.forward_slider)

        self.forward_progress_bar = QProgressBar()
        self.forward_progress_bar.setOrientation(Qt.Vertical)
        self.forward_progress_bar.setRange(int(-100), int(101))
        self.forward_progress_bar.setValue((self.currentForward / 0.075) * 100)
        self.forward_progress_bar.setTextVisible(False)
        hbox.addWidget(self.forward_progress_bar)

        self.forward_progress_bar_label = QLabel()
        self.forward_progress_bar_label.setText("%.6f" % self.currentForward)
        hbox.addWidget(self.forward_progress_bar_label)
        hbox.addStretch()
        widget.setLayout(hbox)
        vbox.addWidget(widget)

        self.lateral_label = QLabel()
        self.lateral_label.setText("Lateral")
        vbox.addWidget(self.lateral_label)

        self.lateral_slider = QSlider(Qt.Horizontal)
        # self.lateral_slider.setText("Lateral")
        self.lateral_slider.setRange(int(-100), int(101))
        self.lateral_slider.setValue(int(0))
        self.lateral_slider.setSingleStep((200) / 50)
        self.lateral_slider.setTickInterval(25)
        self.lateral_slider.valueChanged.connect(self.on_lateralSliderMoved)
        vbox.addWidget(self.lateral_slider)

        self.lateral_progress_bar = QProgressBar()
        self.lateral_progress_bar.setRange(int(-100), int(101))
        self.lateral_progress_bar.setValue((self.currentLateral / 0.15) * 100)
        self.lateral_progress_bar.setFormat("%.6f" % self.currentLateral)
        vbox.addWidget(self.lateral_progress_bar)

        self.height_label = QLabel()
        self.height_label.setText("Height")
        vbox.addWidget(self.height_label)

        widget = QWidget()
        hbox = QHBoxLayout()
        hbox.addStretch()
        self.height_slider = QSlider(Qt.Vertical)
        # self.height_slider.setText("Height")
        self.height_slider.setRange(int(55), int(105))
        self.height_slider.setValue(int(91))
        self.height_slider.setSingleStep(2)
        self.height_slider.setTickInterval(10)
        self.height_slider.valueChanged.connect(self.on_heightSliderMoved)
        hbox.addWidget(self.height_slider)

        self.height_progress_bar = QProgressBar()
        self.height_progress_bar.setOrientation(Qt.Vertical)
        self.height_progress_bar.setRange(int(55), int(105))
        self.height_progress_bar.setValue(self.currentHeight * 100)
        self.height_progress_bar.setTextVisible(False)
        hbox.addWidget(self.height_progress_bar)

        self.height_progress_bar_label = QLabel()
        self.height_progress_bar_label.setText("%.6f" % self.currentHeight)
        hbox.addWidget(self.height_progress_bar_label)
        hbox.addStretch()
        widget.setLayout(hbox)
        vbox.addWidget(widget)
        vbox.addStretch()

        self._widget.setLayout(vbox)
        # context.add_widget(self._widget)
        self.height_position = 0.91
        self.lateral_position = 0.0
        self.yaw_position = 0.0
        self.first_time = True
        self.enable_checkbox.setChecked(False)
        self.yaw_slider.setEnabled(False)
        self.roll_slider.setEnabled(False)
        self.pitch_slider.setEnabled(False)
        self.forward_slider.setEnabled(False)
        self.lateral_slider.setEnabled(False)
        self.height_slider.setEnabled(False)

        self.pub_robot = rospy.Publisher("/flor/controller/bdi_desired_pelvis_pose", PoseStamped, queue_size=10)
        # self.stateSubscriber = rospy.Subscriber('/flor/pelvis_controller/current_states',JointState, self.stateCallbackFnc)
        # self.pub_bdi_pelvis  = rospy.Publisher('/bdi_manipulate_pelvis_pose_rpy',PoseStamped)
        self.pelvis_trajectory_pub = rospy.Publisher(
            "/robot_controllers/pelvis_traj_controller/command", JointTrajectory, queue_size=10
        )
        self.stateSubscriber = rospy.Subscriber(
            "/robot_controllers/pelvis_traj_controller/state", JointTrajectoryControllerState, self.stateCallbackFnc
        )

    def stateCallbackFnc(self, jointState_msg):
        self.updateStateSignal.emit(jointState_msg)

    def shutdown_plugin(self):
        # Just make sure to stop timers and publishers, unsubscribe from Topics etc in the shutdown_plugin method.
        print "Shutdown BDI pelvis height "
        self.pub_robot.unregister()
        self.stateSubscriber.unregister()

    def publishRobotPelvisPose(self):
        print "publishing new pelvis pose ..."
        bdi_pelvis_pose = PoseStamped()
        bdi_pelvis_pose.header.stamp = rospy.Time.now()
        bdi_pelvis_pose.pose.position.x = self.forward_position
        bdi_pelvis_pose.pose.position.y = self.lateral_position
        bdi_pelvis_pose.pose.position.z = self.height_position

        # Use BDI yaw*roll*pitch concatenation
        xaxis, yaxis, zaxis = (1, 0, 0), (0, 1, 0), (0, 0, 1)
        Rx = tf.transformations.rotation_matrix(self.roll_position, xaxis)
        Ry = tf.transformations.rotation_matrix(self.pitch_position, yaxis)
        Rz = tf.transformations.rotation_matrix(self.yaw_position, zaxis)
        R = tf.transformations.concatenate_matrices(Rz, Rx, Ry)
        q = tf.transformations.quaternion_from_matrix(R)

        bdi_pelvis_pose.pose.orientation.w = q[3]
        bdi_pelvis_pose.pose.orientation.x = q[0]
        bdi_pelvis_pose.pose.orientation.y = q[1]
        bdi_pelvis_pose.pose.orientation.z = q[2]

        # w   = math.cos(self.yaw_position*0.5)
        # bdi_pelvis_pose.pose.orientation.x   = 0.0
        # bdi_pelvis_pose.pose.orientation.y   = 0.0
        # bdi_pelvis_pose.pose.orientation.z   = math.sin(self.yaw_position*0.5)

        print bdi_pelvis_pose
        print q
        euler = tf.transformations.euler_from_quaternion(q)
        print euler
        self.pub_robot.publish(bdi_pelvis_pose)

        # Now publish the trajectory form for the new controllers
        trajectory = JointTrajectory()
        trajectory.header.stamp = rospy.Time.now()
        trajectory.joint_names = ["com_v1", "com_v0", "pelvis_height", "pelvis_roll", "pelvis_pitch", "pelvis_yaw"]

        trajectory.points = [JointTrajectoryPoint()]
        trajectory.points[0].positions = [
            self.lateral_position,
            self.forward_position,
            self.height_position,
            self.roll_position,
            self.pitch_position,
            self.yaw_position,
        ]
        trajectory.points[0].velocities = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
        trajectory.points[0].time_from_start = rospy.Duration(0.75)
        self.pelvis_trajectory_pub.publish(trajectory)

    ###################################
    def on_snapCurrentPressed(self):
        print "Snap ", self.name, " values to current pelvis positions"
        self.blockSignals(True)
        self.resetCurrentPelvisSliders()
        self.blockSignals(False)

    def blockSignals(self, block):
        self.yaw_slider.blockSignals(block)
        self.roll_slider.blockSignals(block)
        self.pitch_slider.blockSignals(block)
        self.forward_slider.blockSignals(block)
        self.lateral_slider.blockSignals(block)
        self.height_slider.blockSignals(block)

    def resetCurrentPelvisSliders(self):
        self.yaw_slider.setValue((4.0 / math.pi) * self.currentYaw * 100)
        self.roll_slider.setValue((6.0 / math.pi) * self.currentRoll * 100)
        self.pitch_slider.setValue((6.0 / math.pi) * self.currentPitch * 100)
        self.forward_slider.setValue((self.currentForward / 0.075) * 100)
        self.lateral_slider.setValue((self.currentLateral / 0.15) * 100)
        self.height_slider.setValue(self.currentHeight * 100)
        self.yaw_label.setText("Yaw: " + str(self.currentYaw))
        self.roll_label.setText("Roll: " + str(self.currentRoll))
        self.pitch_label.setText("Pitch: " + str(self.currentPitch))
        self.forward_label.setText("Forward: " + str(self.currentForward))
        self.lateral_label.setText("Lateral: " + str(self.currentLateral))
        self.height_label.setText("Height: " + str(self.currentHeight))
        self.forward_position = self.currentForward
        self.lateral_position = self.currentLateral
        self.height_position = self.currentHeight
        self.roll_position = self.currentRoll
        self.pitch_position = self.currentPitch
        self.yaw_position = self.currentYaw

    def on_updateState(self, jointState_msg):

        self.currentLateral = jointState_msg.actual.positions[0]
        self.currentForward = jointState_msg.actual.positions[1]
        self.currentHeight = jointState_msg.actual.positions[2]
        self.currentRoll = jointState_msg.actual.positions[3]
        self.currentPitch = jointState_msg.actual.positions[4]
        self.currentYaw = jointState_msg.actual.positions[5]

        self.yaw_progress_bar.setValue((4.0 / math.pi) * self.currentYaw * 100)
        self.yaw_progress_bar.setFormat("%.6f" % self.currentYaw)

        self.roll_progress_bar.setValue((6.0 / math.pi) * self.currentRoll * 100)
        self.roll_progress_bar.setFormat("%.6f" % self.currentRoll)

        self.pitch_progress_bar.setValue((6.0 / math.pi) * self.currentPitch * 100)
        self.pitch_progress_bar.setFormat("%.6f" % self.currentPitch)

        self.forward_progress_bar.setValue((self.currentForward / 0.075) * 100)
        self.forward_progress_bar_label.setText("%.6f" % self.currentForward)

        self.lateral_progress_bar.setValue((self.currentLateral / 0.15) * 100)
        self.lateral_progress_bar.setFormat("%.6f" % self.currentYaw)

        self.height_progress_bar.setValue(self.currentHeight * 100)
        self.height_progress_bar_label.setText("%.6f" % self.currentHeight)

    ####################################

    def on_enable_check(self, value):
        print "Toggle the enabling checkbox - current state is ", value
        self.yaw_slider.setEnabled(self.enable_checkbox.isChecked())
        self.roll_slider.setEnabled(self.enable_checkbox.isChecked())
        self.pitch_slider.setEnabled(self.enable_checkbox.isChecked())
        self.forward_slider.setEnabled(self.enable_checkbox.isChecked())
        self.lateral_slider.setEnabled(self.enable_checkbox.isChecked())
        self.height_slider.setEnabled(self.enable_checkbox.isChecked())

    def on_yawSliderMoved(self, value):
        self.yaw_position = (value / 100.0) * math.pi / 4.0
        # print "New yaw=",self.yaw_position
        self.yaw_label.setText("Yaw: " + str(self.yaw_position))

        if self.enable_checkbox.isChecked():
            self.publishRobotPelvisPose()

    def on_rollSliderMoved(self, value):
        self.roll_position = (value / 100.0) * math.pi / 6.0
        self.roll_label.setText("Roll: " + str(self.roll_position))

        if self.enable_checkbox.isChecked():
            self.publishRobotPelvisPose()

    def on_pitchSliderMoved(self, value):
        self.pitch_position = (value / 100.0) * math.pi / 6.0
        self.pitch_label.setText("Pitch: " + str(self.pitch_position))

        if self.enable_checkbox.isChecked():
            self.publishRobotPelvisPose()

    def on_forwardSliderMoved(self, value):
        self.forward_position = (value / 100.0) * 0.075
        # print "New forward=",self.forward_position
        self.forward_label.setText("Forward: " + str(self.forward_position))

        if self.enable_checkbox.isChecked():
            self.publishRobotPelvisPose()

    def on_lateralSliderMoved(self, value):
        self.lateral_position = (value / 100.0) * 0.15
        # print "New lateral=",self.lateral_position
        self.lateral_label.setText("Lateral: " + str(self.lateral_position))

        if self.enable_checkbox.isChecked():
            self.publishRobotPelvisPose()

    def on_heightSliderMoved(self, value):
        self.height_position = value / 100.0
        # print "New height=",self.height_position
        self.height_label.setText("Height: " + str(self.height_position))

        if self.enable_checkbox.isChecked():
            self.publishRobotPelvisPose()
class GroupWidget(QWidget):
    '''
    (Isaac's guess as of 12/13/2012)
    This class bonds multiple Editor instances that are associated with
    a single node as a group.
    '''

    # public signal
    sig_node_disabled_selected = Signal(str)

    def __init__(self, updater, config, nodename):
        '''
        :param config:
        :type config: Dictionary? defined in dynamic_reconfigure.client.Client
        :type nodename: str
        '''

        #TODO figure out what data type 'config' is. It is afterall returned
        #     from dynamic_reconfigure.client.get_parameter_descriptions()
        # ros.org/doc/api/dynamic_reconfigure/html/dynamic_reconfigure.client-pysrc.html#Client

        super(GroupWidget, self).__init__()
        self.state = config['state']
        self.name = config['name']
        self._toplevel_treenode_name = nodename

        # TODO: .ui file needs to be back into usage in later phase.
#        ui_file = os.path.join(rp.get_path('rqt_reconfigure'),
#                               'resource', 'singlenode_parameditor.ui')
#        loadUi(ui_file, self)

        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(QMargins(0, 0, 0, 0))

        _widget_nodeheader = QWidget()
        _h_layout_nodeheader = QHBoxLayout(_widget_nodeheader)
        _h_layout_nodeheader.setContentsMargins(QMargins(0, 0, 0, 0))

        self.nodename_qlabel = QLabel(self)
        font = QFont('Trebuchet MS, Bold')
        font.setUnderline(True)
        font.setBold(True)

        # Button to close a node.
        _icon_disable_node = QIcon.fromTheme('window-close')
        _bt_disable_node = QPushButton(_icon_disable_node, '', self)
        _bt_disable_node.setToolTip('Hide this node')
        _bt_disable_node_size = QSize(36, 24)
        _bt_disable_node.setFixedSize(_bt_disable_node_size)
        _bt_disable_node.pressed.connect(self._node_disable_bt_clicked)

        _h_layout_nodeheader.addWidget(self.nodename_qlabel)
        _h_layout_nodeheader.addWidget(_bt_disable_node)

        self.nodename_qlabel.setAlignment(Qt.AlignCenter)
        font.setPointSize(10)
        self.nodename_qlabel.setFont(font)
        grid_widget = QWidget(self)
        self.grid = QFormLayout(grid_widget)
        verticalLayout.addWidget(_widget_nodeheader)
        verticalLayout.addWidget(grid_widget, 1)
        # Again, these UI operation above needs to happen in .ui file.

        self.tab_bar = None  # Every group can have one tab bar
        self.tab_bar_shown = False

        self.updater = updater

        self.editor_widgets = []
        self._param_names = []

        self._create_node_widgets(config)

        rospy.logdebug('Groups node name={}'.format(nodename))
        self.nodename_qlabel.setText(nodename)

        # Labels should not stretch
        #self.grid.setColumnStretch(1, 1)
        #self.setLayout(self.grid)

    def collect_paramnames(self, config):
        pass

    def _create_node_widgets(self, config):
        '''
        :type config: Dict?
        '''
        i_debug = 0
        for param in config['parameters']:
            begin = time.time() * 1000
            editor_type = '(none)'

            if param['edit_method']:
                widget = EnumEditor(self.updater, param)
            elif param['type'] in EDITOR_TYPES:
                rospy.logdebug('GroupWidget i_debug=%d param type =%s',
                              i_debug,
                              param['type'])
                editor_type = EDITOR_TYPES[param['type']]
                widget = eval(editor_type)(self.updater, param)

            self.editor_widgets.append(widget)
            self._param_names.append(param['name'])

            rospy.logdebug('groups._create_node_widgets num editors=%d',
                           i_debug)

            end = time.time() * 1000
            time_elap = end - begin
            rospy.logdebug('ParamG editor={} loop=#{} Time={}msec'.format(
                                              editor_type, i_debug, time_elap))
            i_debug += 1

        for name, group in config['groups'].items():
            if group['type'] == 'tab':
                widget = TabGroup(self, self.updater, group)
            elif group['type'] in _GROUP_TYPES.keys():
                widget = eval(_GROUP_TYPES[group['type']])(self.updater, group)

            self.editor_widgets.append(widget)
            rospy.logdebug('groups._create_node_widgets ' +
                          #'num groups=%d' +
                          'name=%s',
                          name)

        for i, ed in enumerate(self.editor_widgets):
            ed.display(self.grid)

        rospy.logdebug('GroupWdgt._create_node_widgets len(editor_widgets)=%d',
                      len(self.editor_widgets))

    def display(self, grid, row):
        # groups span across all columns
        grid.addWidget(self, row, 0, 1, -1)

    def update_group(self, config):
        self.state = config['state']

        # TODO: should use config.keys but this method doesnt exist
        names = [name for name in config.items()]

        for widget in self.editor_widgets:
            if isinstance(widget, EditorWidget):
                if widget.name in names:
                    widget.update_value(config[widget.name])
            elif isinstance(widget, GroupWidget):
                cfg = find_cfg(config, widget.name)
                widget.update_group(cfg)

    def close(self):
        for w in self.editor_widgets:
            w.close()

    def get_treenode_names(self):
        '''
        :rtype: str[]
        '''
        return self._param_names

    def _node_disable_bt_clicked(self):
        rospy.logdebug('param_gs _node_disable_bt_clicked')
        self.sig_node_disabled_selected.emit(self._toplevel_treenode_name)
    def __init__(self, parent, fileName, widget):

        self.controllers = []
        self.parent      = parent

        self.loadFile(fileName)

        robot = URDF.from_parameter_server()
        joint_list = {}
	for ndx,jnt in enumerate(robot.joints):
		joint_list[jnt.name] = ndx

        for controller in self.controllers:
            frame = QFrame()
            frame.setFrameShape(QFrame.StyledPanel);
            frame.setFrameShadow(QFrame.Raised);

            vbox = QVBoxLayout()
            label = QLabel()
            label.setText(controller.label)
            vbox.addWidget(label);
            print controller.name

            controller.snap_to_ghost_button = QPushButton("SnapGhost")
            controller.snap_to_ghost_button.pressed.connect(controller.on_snapGhostPressed)
            vbox.addWidget(controller.snap_to_ghost_button)
            controller.snap_to_current_button = QPushButton("SnapCurrent")
            controller.snap_to_current_button.pressed.connect(controller.on_snapCurrentPressed)
            vbox.addWidget(controller.snap_to_current_button)
            controller.apply_to_robot_button = QPushButton("ApplyRobot")
            controller.apply_to_robot_button.pressed.connect(controller.on_applyRobotPressed)
            vbox.addWidget(controller.apply_to_robot_button)
            controller.save_joints_to_file_button = QPushButton("SaveJoints")
            controller.save_joints_to_file_button.pressed.connect(controller.on_saveJointsPressed)
            vbox.addWidget(controller.save_joints_to_file_button)
            controller.undo_last_action_button = QPushButton("Undo Last")
            controller.undo_last_action_button.pressed.connect(controller.on_undoPressed)
            vbox.addWidget(controller.undo_last_action_button)


            for joint in controller.joints:
                label = QLabel()
                label.setText(joint.name)
                vbox.addWidget(label);

                robot_joint = robot.joints[joint_list[joint.name]]
                lower = robot_joint.limit.lower - (math.fabs(robot_joint.limit.upper)+math.fabs(robot_joint.limit.lower))*0.2
                upper = robot_joint.limit.upper + (math.fabs(robot_joint.limit.upper)+math.fabs(robot_joint.limit.lower))*0.2
                print "  ",joint.name, "  limits(", robot_joint.limit.lower,", ",robot_joint.limit.upper,") num"

                joint.slider = QSlider(Qt.Horizontal)
                joint.slider.setRange(int(lower*10000.0), int(upper*10000.0))
                joint.slider.setValue(int(lower*10000.0))
                joint.slider.setSingleStep((upper-lower)/20.0)
                joint.slider.valueChanged.connect(joint.on_sliderMoved)
                vbox.addWidget(joint.slider)
                joint.progress_bar = QProgressBar()
                joint.progress_bar.setRange(int(lower*10000.0), int(upper*10000.0))
                joint.progress_bar.setValue(int(lower*10000.0))
                vbox.addWidget(joint.progress_bar)

            vbox.addStretch()

            frame.setLayout(vbox)
            widget.addWidget(frame)
    def __init__(self, updater, config, nodename):
        '''
        :param config:
        :type config: Dictionary? defined in dynamic_reconfigure.client.Client
        :type nodename: str
        '''

        #TODO figure out what data type 'config' is. It is afterall returned
        #     from dynamic_reconfigure.client.get_parameter_descriptions()
        # ros.org/doc/api/dynamic_reconfigure/html/dynamic_reconfigure.client-pysrc.html#Client

        super(GroupWidget, self).__init__()
        self.state = config['state']
        self.name = config['name']
        self._toplevel_treenode_name = nodename

        # TODO: .ui file needs to be back into usage in later phase.
#        ui_file = os.path.join(rp.get_path('rqt_reconfigure'),
#                               'resource', 'singlenode_parameditor.ui')
#        loadUi(ui_file, self)

        verticalLayout = QVBoxLayout(self)
        verticalLayout.setContentsMargins(QMargins(0, 0, 0, 0))

        _widget_nodeheader = QWidget()
        _h_layout_nodeheader = QHBoxLayout(_widget_nodeheader)
        _h_layout_nodeheader.setContentsMargins(QMargins(0, 0, 0, 0))

        self.nodename_qlabel = QLabel(self)
        font = QFont('Trebuchet MS, Bold')
        font.setUnderline(True)
        font.setBold(True)

        # Button to close a node.
        _icon_disable_node = QIcon.fromTheme('window-close')
        _bt_disable_node = QPushButton(_icon_disable_node, '', self)
        _bt_disable_node.setToolTip('Hide this node')
        _bt_disable_node_size = QSize(36, 24)
        _bt_disable_node.setFixedSize(_bt_disable_node_size)
        _bt_disable_node.pressed.connect(self._node_disable_bt_clicked)

        _h_layout_nodeheader.addWidget(self.nodename_qlabel)
        _h_layout_nodeheader.addWidget(_bt_disable_node)

        self.nodename_qlabel.setAlignment(Qt.AlignCenter)
        font.setPointSize(10)
        self.nodename_qlabel.setFont(font)
        grid_widget = QWidget(self)
        self.grid = QFormLayout(grid_widget)
        verticalLayout.addWidget(_widget_nodeheader)
        verticalLayout.addWidget(grid_widget, 1)
        # Again, these UI operation above needs to happen in .ui file.

        self.tab_bar = None  # Every group can have one tab bar
        self.tab_bar_shown = False

        self.updater = updater

        self.editor_widgets = []
        self._param_names = []

        self._create_node_widgets(config)

        rospy.logdebug('Groups node name={}'.format(nodename))
        self.nodename_qlabel.setText(nodename)
    def __init__(self, context, node=None):
        """
        This class is intended to be called by rqt plugin framework class.
        Currently (12/12/2012) the whole widget is splitted into 2 panes:
        one on left allows you to choose the node(s) you work on. Right side
        pane lets you work with the parameters associated with the node(s) you
        select on the left.

        (12/27/2012) Despite the pkg name is changed to rqt_reconfigure to
        reflect the available functionality, file & class names remain
        'param', expecting all the parameters will become handle-able.
        """

        super(ParamWidget, self).__init__()
        self.setObjectName(self._TITLE_PLUGIN)
        self.setWindowTitle(self._TITLE_PLUGIN)

        rp = rospkg.RosPack()

        #TODO: .ui file needs to replace the GUI components declaration
        #            below. For unknown reason, referring to another .ui files
        #            from a .ui that is used in this class failed. So for now,
        #            I decided not use .ui in this class.
        #            If someone can tackle this I'd appreciate.
        _hlayout_top = QHBoxLayout(self)
        _hlayout_top.setContentsMargins(QMargins(0, 0, 0, 0))
        self._splitter = QSplitter(self)
        _hlayout_top.addWidget(self._splitter)

        _vlayout_nodesel_widget = QWidget()
        _vlayout_nodesel_side = QVBoxLayout()
        _hlayout_filter_widget = QWidget(self)
        _hlayout_filter = QHBoxLayout()
        self._text_filter = TextFilter()
        self.filter_lineedit = TextFilterWidget(self._text_filter, rp)
        self.filterkey_label = QLabel("&Filter key:")
        self.filterkey_label.setBuddy(self.filter_lineedit)
        _hlayout_filter.addWidget(self.filterkey_label)
        _hlayout_filter.addWidget(self.filter_lineedit)
        _hlayout_filter_widget.setLayout(_hlayout_filter)
        self._nodesel_widget = NodeSelectorWidget(self, rp, self.sig_sysmsg)
        _vlayout_nodesel_side.addWidget(_hlayout_filter_widget)
        _vlayout_nodesel_side.addWidget(self._nodesel_widget)
        _vlayout_nodesel_side.setSpacing(1)
        _vlayout_nodesel_widget.setLayout(_vlayout_nodesel_side)

        reconf_widget = ParameditWidget(rp)

        self._splitter.insertWidget(0, _vlayout_nodesel_widget)
        self._splitter.insertWidget(1, reconf_widget)
        # 1st column, _vlayout_nodesel_widget, to minimize width.
        # 2nd col to keep the possible max width.
        self._splitter.setStretchFactor(0, 0)
        self._splitter.setStretchFactor(1, 1)

        # Signal from paramedit widget to node selector widget.
        reconf_widget.sig_node_disabled_selected.connect(
                                       self._nodesel_widget.node_deselected)
        # Pass name of node to editor widget
        self._nodesel_widget.sig_node_selected.connect(
                                                     reconf_widget.show_reconf)

        if not node:
            title = self._TITLE_PLUGIN
        else:
            title = self._TITLE_PLUGIN + ' %s' % node
        self.setObjectName(title)

        #Connect filter signal-slots.
        self._text_filter.filter_changed_signal.connect(
                                            self._filter_key_changed)

        # Open any clients indicated from command line
        self.sig_selected.connect(self._nodesel_widget.node_selected)
        for rn in [rospy.resolve_name(c) for c in context.argv()]:
            if rn in self._nodesel_widget.get_paramitems():
                self.sig_selected.emit(rn)
            else:
                rospy.logwarn('Could not find a dynamic reconfigure client named \'%s\'', str(rn))
 def _add_track_label(self, track_name, background_color=None):
     label = QLabel(track_name)
     label.setMargin(5)
     palette = label.palette()
     palette.setColor(label.foregroundRole(), Qt.black)
     if background_color is not None:
         label.setAutoFillBackground(True)
         palette.setColor(label.backgroundRole(), background_color)
     label.setPalette(palette)
     label.setFont(QFont('sans', 13))
     self.track_label_layout.addWidget(label)
Exemple #58
0
class Editor(QMainWindow):
    '''
    Creates a dialog to edit a launch file.
    '''
    finished_signal = Signal(list)
    '''
    finished_signal has as parameter the filenames of the initialization and is emitted, if this
    dialog was closed.
    '''

    def __init__(self, filenames, search_text='', parent=None):
        '''
        @param filenames: a list with filenames. The last one will be activated.
        @type filenames: C{[str, ...]}
        @param search_text: if not empty, searches in new document for first occurrence of the given text
        @type search_text: C{str} (Default: C{Empty String})
        '''
        QMainWindow.__init__(self, parent)
        self.setObjectName(' - '.join(['Editor', str(filenames)]))
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.setWindowFlags(Qt.Window)
        self.mIcon = QIcon(":/icons/crystal_clear_edit_launch.png")
        self._error_icon = QIcon(":/icons/crystal_clear_warning.png")
        self._empty_icon = QIcon()
        self.setWindowIcon(self.mIcon)
        window_title = "ROSLaunch Editor"
        if filenames:
            window_title = self.__getTabName(filenames[0])
        self.setWindowTitle(window_title)
        self.init_filenames = list(filenames)
        self._search_thread = None
        # list with all open files
        self.files = []
        # create tabs for files
        self.main_widget = QWidget(self)
        self.verticalLayout = QVBoxLayout(self.main_widget)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setSpacing(1)
        self.verticalLayout.setObjectName("verticalLayout")

        self.tabWidget = EditorTabWidget(self)
        self.tabWidget.setTabPosition(QTabWidget.North)
        self.tabWidget.setDocumentMode(True)
        self.tabWidget.setTabsClosable(True)
        self.tabWidget.setMovable(False)
        self.tabWidget.setObjectName("tabWidget")
        self.tabWidget.tabCloseRequested.connect(self.on_close_tab)

        self.verticalLayout.addWidget(self.tabWidget)
        self.buttons = self._create_buttons()
        self.verticalLayout.addWidget(self.buttons)
        self.setCentralWidget(self.main_widget)

        self.find_dialog = TextSearchFrame(self.tabWidget, self)
        self.find_dialog.search_result_signal.connect(self.on_search_result)
        self.find_dialog.replace_signal.connect(self.on_replace)
        self.addDockWidget(Qt.RightDockWidgetArea, self.find_dialog)
        # open the files
        for f in filenames:
            if f:
                self.on_load_request(os.path.normpath(f), search_text)
        self.readSettings()
        self.find_dialog.setVisible(False)

#  def __del__(self):
#    print "******** destroy", self.objectName()

    def _create_buttons(self):
        # create the buttons line
        self.buttons = QWidget(self)
        self.horizontalLayout = QHBoxLayout(self.buttons)
        self.horizontalLayout.setContentsMargins(4, 0, 4, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        # add the search button
        self.searchButton = QPushButton(self)
        self.searchButton.setObjectName("searchButton")
#        self.searchButton.clicked.connect(self.on_shortcut_find)
        self.searchButton.toggled.connect(self.on_toggled_find)
        self.searchButton.setText(self._translate("&Find"))
        self.searchButton.setToolTip('Open a search dialog (Ctrl+F)')
        self.searchButton.setFlat(True)
        self.searchButton.setCheckable(True)
        self.horizontalLayout.addWidget(self.searchButton)
        # add the replace button
        self.replaceButton = QPushButton(self)
        self.replaceButton.setObjectName("replaceButton")
#        self.replaceButton.clicked.connect(self.on_shortcut_replace)
        self.replaceButton.toggled.connect(self.on_toggled_replace)
        self.replaceButton.setText(self._translate("&Replace"))
        self.replaceButton.setToolTip('Open a search&replace dialog (Ctrl+R)')
        self.replaceButton.setFlat(True)
        self.replaceButton.setCheckable(True)
        self.horizontalLayout.addWidget(self.replaceButton)
        # add the goto button
        self.gotoButton = QPushButton(self)
        self.gotoButton.setObjectName("gotoButton")
        self.gotoButton.clicked.connect(self.on_shortcut_goto)
        self.gotoButton.setText(self._translate("&Goto line"))
        self.gotoButton.setShortcut("Ctrl+G")
        self.gotoButton.setToolTip('Open a goto dialog (Ctrl+G)')
        self.gotoButton.setFlat(True)
        self.horizontalLayout.addWidget(self.gotoButton)
        # add a tag button
        self.tagButton = self._create_tag_button(self)
        self.horizontalLayout.addWidget(self.tagButton)
        # add spacer
        spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        # add line number label
        self.pos_label = QLabel()
        self.horizontalLayout.addWidget(self.pos_label)
        # add spacer
        spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        # add save button
        self.saveButton = QPushButton(self)
        self.saveButton.setObjectName("saveButton")
        self.saveButton.clicked.connect(self.on_saveButton_clicked)
        self.saveButton.setText(self._translate("&Save"))
        self.saveButton.setShortcut("Ctrl+S")
        self.saveButton.setToolTip('Save the changes to the file (Ctrl+S)')
        self.saveButton.setFlat(True)
        self.horizontalLayout.addWidget(self.saveButton)
        return self.buttons

    def keyPressEvent(self, event):
        '''
        Enable the shortcats for search and replace
        '''
        if event.key() == Qt.Key_Escape:
            self.reject()
        elif event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_F:
            if self.tabWidget.currentWidget().hasFocus():
                if not self.searchButton.isChecked():
                    self.searchButton.setChecked(True)
                else:
                    self.on_toggled_find(True)
            else:
                self.searchButton.setChecked(not self.searchButton.isChecked())
        elif event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_R:
            if self.tabWidget.currentWidget().hasFocus():
                if not self.replaceButton.isChecked():
                    self.replaceButton.setChecked(True)
                else:
                    self.on_toggled_replace(True)
            else:
                self.replaceButton.setChecked(not self.replaceButton.isChecked())
        else:
            event.accept()
            QMainWindow.keyPressEvent(self, event)

    def _translate(self, text):
        if hasattr(QApplication, "UnicodeUTF8"):
            return QApplication.translate("Editor", text, None, QApplication.UnicodeUTF8)
        else:
            return QApplication.translate("Editor", text, None)

    def readSettings(self):
        if nm.settings().store_geometry:
            settings = nm.settings().qsettings(nm.settings().CFG_GUI_FILE)
            settings.beginGroup("editor")
            maximized = settings.value("maximized", 'false') == 'true'
            if maximized:
                self.showMaximized()
            else:
                self.resize(settings.value("size", QSize(800, 640)))
                self.move(settings.value("pos", QPoint(0, 0)))
            try:
                self.restoreState(settings.value("window_state"))
            except:
                import traceback
                print traceback.format_exc()
            settings.endGroup()

    def storeSetting(self):
        if nm.settings().store_geometry:
            settings = nm.settings().qsettings(nm.settings().CFG_GUI_FILE)
            settings.beginGroup("editor")
            settings.setValue("size", self.size())
            settings.setValue("pos", self.pos())
            settings.setValue("maximized", self.isMaximized())
            settings.setValue("window_state", self.saveState())
            settings.endGroup()

    def on_load_request(self, filename, search_text=''):
        '''
        Loads a file in a new tab or focus the tab, if the file is already open.
        @param filename: the path to file
        @type filename: C{str}
        @param search_text: if not empty, searches in new document for first occurrence of the given text
        @type search_text: C{str} (Default: C{Empty String})
        '''
        if not filename:
            return
        self.tabWidget.setUpdatesEnabled(False)
        try:
            if filename not in self.files:
                tab_name = self.__getTabName(filename)
                editor = TextEdit(filename, self.tabWidget)
                linenumber_editor = LineNumberWidget(editor)
                tab_index = self.tabWidget.addTab(linenumber_editor, tab_name)
                self.files.append(filename)
                editor.setCurrentPath(os.path.basename(filename))
                editor.load_request_signal.connect(self.on_load_request)
                editor.document().modificationChanged.connect(self.on_editor_modificationChanged)
                editor.cursorPositionChanged.connect(self.on_editor_positionChanged)
                editor.setFocus(Qt.OtherFocusReason)
#                editor.textChanged.connect(self.on_text_changed)
                editor.undoAvailable.connect(self.on_text_changed)
                self.tabWidget.setCurrentIndex(tab_index)
#                self.find_dialog.set_search_path(filename)
            else:
                for i in range(self.tabWidget.count()):
                    if self.tabWidget.widget(i).filename == filename:
                        self.tabWidget.setCurrentIndex(i)
                        break
        except:
            import traceback
            rospy.logwarn("Error while open %s: %s", filename, traceback.format_exc(1))
        self.tabWidget.setUpdatesEnabled(True)
        if search_text:
            try:
                self._search_thread.stop()
                self._search_thread = None
            except:
                pass
            self._search_thread = TextSearchThread(search_text, filename, path_text=self.tabWidget.widget(0).document().toPlainText(), recursive=True)
            self._search_thread.search_result_signal.connect(self.on_search_result_on_open)
            self._search_thread.start()

    def on_text_changed(self, value=""):
        if self.tabWidget.currentWidget().hasFocus():
            self.find_dialog.file_changed(self.tabWidget.currentWidget().filename)

    def on_close_tab(self, tab_index):
        '''
        Signal handling to close single tabs.
        @param tab_index: tab index to close
        @type tab_index: C{int}
        '''
        try:
            doremove = True
            w = self.tabWidget.widget(tab_index)
            if w.document().isModified():
                name = self.__getTabName(w.filename)
                result = QMessageBox.question(self, "Unsaved Changes", '\n\n'.join(["Save the file before closing?", name]), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
                if result == QMessageBox.Yes:
                    self.tabWidget.currentWidget().save()
                elif result == QMessageBox.No:
                    pass
                else:
                    doremove = False
            if doremove:
                # remove the indexed files
                if w.filename in self.files:
                    self.files.remove(w.filename)
                # close tab
                self.tabWidget.removeTab(tab_index)
                # close editor, if no tabs are open
                if not self.tabWidget.count():
                    self.close()
        except:
            import traceback
            rospy.logwarn("Error while close tab %s: %s", str(tab_index), traceback.format_exc(1))

    def reject(self):
        if self.find_dialog.isVisible():
            self.searchButton.setChecked(not self.searchButton.isChecked())
        else:
            self.close()

    def closeEvent(self, event):
        '''
        Test the open files for changes and save this if needed.
        '''
        changed = []
        # get the names of all changed files
        for i in range(self.tabWidget.count()):
            w = self.tabWidget.widget(i)
            if w.document().isModified():
                changed.append(self.__getTabName(w.filename))
        if changed:
            # ask the user for save changes
            if self.isHidden():
                buttons = QMessageBox.Yes | QMessageBox.No
            else:
                buttons = QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel
            result = QMessageBox.question(self, "Unsaved Changes", '\n\n'.join(["Save the file before closing?", '\n'.join(changed)]), buttons)
            if result == QMessageBox.Yes:
                for i in range(self.tabWidget.count()):
                    w = self.tabWidget.widget(i).save()
                event.accept()
            elif result == QMessageBox.No:
                event.accept()
            else:
                event.ignore()
        else:
            event.accept()
        if event.isAccepted():
            self.storeSetting()
            self.finished_signal.emit(self.init_filenames)

    def on_editor_modificationChanged(self, value=None):
        '''
        If the content was changed, a '*' will be shown in the tab name.
        '''
        tab_name = self.__getTabName(self.tabWidget.currentWidget().filename)
        if (self.tabWidget.currentWidget().document().isModified()) or not QFileInfo(self.tabWidget.currentWidget().filename).exists():
            tab_name = ''.join(['*', tab_name])
        self.tabWidget.setTabText(self.tabWidget.currentIndex(), tab_name)

    def on_editor_positionChanged(self):
        '''
        Shows the number of the line and column in a label.
        '''
        cursor = self.tabWidget.currentWidget().textCursor()
        self.pos_label.setText(':%s:%s #%s' % (cursor.blockNumber() + 1, cursor.columnNumber(), cursor.position()))

    def __getTabName(self, lfile):
        base = os.path.basename(lfile).replace('.launch', '')
        (package, _) = package_name(os.path.dirname(lfile))
        return '%s [%s]' % (base, package)

    ##############################################################################
    # HANDLER for buttons
    ##############################################################################

    def on_saveButton_clicked(self):
        '''
        Saves the current document. This method is called if the C{save button}
        was clicked.
        '''
        saved, errors, msg = self.tabWidget.currentWidget().save(True)
        if errors:
            QMessageBox.critical(self, "Error", msg)
            self.tabWidget.setTabIcon(self.tabWidget.currentIndex(), self._error_icon)
            self.tabWidget.setTabToolTip(self.tabWidget.currentIndex(), msg)
        elif saved:
            self.tabWidget.setTabIcon(self.tabWidget.currentIndex(), self._empty_icon)
            self.tabWidget.setTabToolTip(self.tabWidget.currentIndex(), '')

    def on_shortcut_find(self):
        pass

    def on_toggled_find(self, value):
        '''
        Shows the search frame
        '''
        if value:
            self.find_dialog.enable()
        else:
            self.replaceButton.setChecked(False)
            self.find_dialog.setVisible(False)
            self.tabWidget.currentWidget().setFocus()

    def on_toggled_replace(self, value):
        '''
        Shows the replace lineedit in the search frame
        '''
        if value:
            self.searchButton.setChecked(True)
        self.find_dialog.set_replace_visible(value)

    def on_shortcut_goto(self):
        '''
        Opens a C{goto} dialog.
        '''
        value = 1
        ok = False
        try:
            value, ok = QInputDialog.getInt(self, "Goto", self.tr("Line number:"),
                                                  QLineEdit.Normal, minValue=1, step=1)
        except:
            value, ok = QInputDialog.getInt(self, "Goto", self.tr("Line number:"),
                                                  QLineEdit.Normal, min=1, step=1)
        if ok:
            if value > self.tabWidget.currentWidget().document().blockCount():
                value = self.tabWidget.currentWidget().document().blockCount()
            curpos = self.tabWidget.currentWidget().textCursor().blockNumber() + 1
            while curpos != value:
                mov = QTextCursor.NextBlock if curpos < value else QTextCursor.PreviousBlock
                self.tabWidget.currentWidget().moveCursor(mov)
                curpos = self.tabWidget.currentWidget().textCursor().blockNumber() + 1
        self.tabWidget.currentWidget().setFocus(Qt.ActiveWindowFocusReason)

    ##############################################################################
    # SLOTS for search dialog
    ##############################################################################

    def on_search_result(self, search_text, found, path, index):
        '''
        A slot to handle a found text. It goes to the position in the text and select
        the searched text. On new file it will be open.
        :param search_text: the searched text
        :type search_text: str
        :param found: the text was found or not
        :type found: bool
        :param path: the path of the file the text was found
        :type path: str
        :param index: the position in the text
        :type index: int
        '''
        if found:
            if self.tabWidget.currentWidget().filename != path:
                focus_widget = QApplication.focusWidget()
                self.on_load_request(path)
                focus_widget.setFocus()
            cursor = self.tabWidget.currentWidget().textCursor()
            cursor.setPosition(index, QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor, len(search_text))
            self.tabWidget.currentWidget().setTextCursor(cursor)

    def on_search_result_on_open(self, search_text, found, path, index):
        '''
        Like on_search_result, but skips the text in comments.
        '''
        if found:
            if self.tabWidget.currentWidget().filename != path:
                focus_widget = QApplication.focusWidget()
                self.on_load_request(path)
                focus_widget.setFocus()
            comment_start = self.tabWidget.currentWidget().document().find('<!--', index, QTextDocument.FindBackward)
            if not comment_start.isNull():
                comment_end = self.tabWidget.currentWidget().document().find('-->', comment_start)
                if not comment_end.isNull() and comment_end.position() > index + len(search_text):
                    # commented -> retrun
                    return
        self.on_search_result(search_text, found, path, index)

    def on_replace(self, search_text, path, index, replaced_text):
        '''
        A slot to handle a text replacement of the TextSearchFrame.
        :param search_text: the searched text
        :type search_text: str
        :param path: the path of the file the text was found
        :type path: str
        :param index: the position in the text
        :type index: int
        :param replaced_text: the new text
        :type replaced_text: str
        '''
        cursor = self.tabWidget.currentWidget().textCursor()
        if cursor.selectedText() == search_text:
            cursor.insertText(replaced_text)

    ##############################################################################
    # LAUNCH TAG insertion
    ##############################################################################

    def _create_tag_button(self, parent=None):
        btn = QPushButton(parent)
        btn.setObjectName("tagButton")
        btn.setText(self._translate("Add &tag"))
        btn.setShortcut("Ctrl+T")
        btn.setToolTip('Adds a ROS launch tag to launch file (Ctrl+T)')
        btn.setMenu(self._create_tag_menu(btn))
        btn.setFlat(True)
        return btn

    def _create_tag_menu(self, parent=None):
        # creates a tag menu
        tag_menu = QMenu("ROS Tags", parent)
        # group tag
        add_group_tag_action = QAction("<group>", self, statusTip="", triggered=self._on_add_group_tag)
        add_group_tag_action.setShortcuts(QKeySequence("Ctrl+Shift+g"))
        tag_menu.addAction(add_group_tag_action)
        # node tag
        add_node_tag_action = QAction("<node>", self, statusTip="", triggered=self._on_add_node_tag)
        add_node_tag_action.setShortcuts(QKeySequence("Ctrl+Shift+n"))
        tag_menu.addAction(add_node_tag_action)
        # node tag with all attributes
        add_node_tag_all_action = QAction("<node all>", self, statusTip="", triggered=self._on_add_node_tag_all)
        tag_menu.addAction(add_node_tag_all_action)
        # include tag with all attributes
        add_include_tag_all_action = QAction("<include>", self, statusTip="", triggered=self._on_add_include_tag_all)
        add_include_tag_all_action.setShortcuts(QKeySequence("Ctrl+Shift+i"))
        tag_menu.addAction(add_include_tag_all_action)
        # remap
        add_remap_tag_action = QAction("<remap>", self, statusTip="", triggered=self._on_add_remap_tag)
        add_remap_tag_action.setShortcuts(QKeySequence("Ctrl+Shift+r"))
        tag_menu.addAction(add_remap_tag_action)
        # env tag
        add_env_tag_action = QAction("<env>", self, statusTip="", triggered=self._on_add_env_tag)
        tag_menu.addAction(add_env_tag_action)
        # param tag
        add_param_tag_action = QAction("<param>", self, statusTip="", triggered=self._on_add_param_tag)
        add_param_tag_action.setShortcuts(QKeySequence("Ctrl+Shift+p"))
        tag_menu.addAction(add_param_tag_action)
        # param capability group tag
        add_param_cap_group_tag_action = QAction("<param capability group>", self, statusTip="", triggered=self._on_add_param_cap_group_tag)
        add_param_cap_group_tag_action.setShortcuts(QKeySequence("Ctrl+Alt+p"))
        tag_menu.addAction(add_param_cap_group_tag_action)
        # param tag with all attributes
        add_param_tag_all_action = QAction("<param all>", self, statusTip="", triggered=self._on_add_param_tag_all)
        tag_menu.addAction(add_param_tag_all_action)
        # rosparam tag with all attributes
        add_rosparam_tag_all_action = QAction("<rosparam>", self, statusTip="", triggered=self._on_add_rosparam_tag_all)
        tag_menu.addAction(add_rosparam_tag_all_action)
        # arg tag with default definition
        add_arg_tag_default_action = QAction("<arg default>", self, statusTip="", triggered=self._on_add_arg_tag_default)
        add_arg_tag_default_action.setShortcuts(QKeySequence("Ctrl+Shift+a"))
        tag_menu.addAction(add_arg_tag_default_action)
        # arg tag with value definition
        add_arg_tag_value_action = QAction("<arg value>", self, statusTip="", triggered=self._on_add_arg_tag_value)
        add_arg_tag_value_action.setShortcuts(QKeySequence("Ctrl+Alt+a"))
        tag_menu.addAction(add_arg_tag_value_action)

        # test tag
        add_test_tag_action = QAction("<test>", self, statusTip="", triggered=self._on_add_test_tag)
        add_test_tag_action.setShortcuts(QKeySequence("Ctrl+Alt+t"))
        tag_menu.addAction(add_test_tag_action)
        # test tag with all attributes
        add_test_tag_all_action = QAction("<test all>", self, statusTip="", triggered=self._on_add_test_tag_all)
        tag_menu.addAction(add_test_tag_all_action)
        return tag_menu

    def _insert_text(self, text):
        cursor = self.tabWidget.currentWidget().textCursor()
        if not cursor.isNull():
            col = cursor.columnNumber()
            spaces = ''.join([' ' for _ in range(col)])
            cursor.insertText(text.replace('\n', '\n%s' % spaces))
            self.tabWidget.currentWidget().setFocus(Qt.OtherFocusReason)

    def _on_add_group_tag(self):
        self._insert_text('<group ns="namespace" clear_params="true|false">\n'
                          '</group>')

    def _on_add_node_tag(self):
        dia = PackageDialog()
        if dia.exec_():
            self._insert_text('<node name="%s" pkg="%s" type="%s">\n'
                              '</node>' % (dia.binary, dia.package, dia.binary))

    def _on_add_node_tag_all(self):
        dia = PackageDialog()
        if dia.exec_():
            self._insert_text('<node name="%s" pkg="%s" type="%s"\n'
                              '      args="arg1" machine="machine-name"\n'
                              '      respawn="true" required="true"\n'
                              '      ns="foo" clear_params="true|false"\n'
                              '      output="log|screen" cwd="ROS_HOME|node"\n'
                              '      launch-prefix="prefix arguments">\n'
                              '</node>' % (dia.binary, dia.package, dia.binary))

    def _on_add_include_tag_all(self):
        self._insert_text('<include file="$(find pkg-name)/path/filename.xml"\n'
                          '         ns="foo" clear_params="true|false">\n'
                          '</include>')

    def _on_add_remap_tag(self):
        self._insert_text('<remap from="original" to="new"/>')

    def _on_add_env_tag(self):
        self._insert_text('<env name="variable" value="value"/>')

    def _on_add_param_tag(self):
        self._insert_text('<param name="ns_name" value="value" />')

    def _on_add_param_cap_group_tag(self):
        self._insert_text('<param name="capability_group" value="demo" />')

    def _on_add_param_tag_all(self):
        self._insert_text('<param name="ns_name" value="value"\n'
                          '       type="str|int|double|bool"\n'
                          '       textfile="$(find pkg-name)/path/file.txt"\n'
                          '       binfile="$(find pkg-name)/path/file"\n'
                          '       command="$(find pkg-name)/exe \'$(find pkg-name)/arg.txt\'">\n'
                          '</param>')

    def _on_add_rosparam_tag_all(self):
        self._insert_text('<rosparam param="param-name"\n'
                          '       file="$(find pkg-name)/path/foo.yaml"\n'
                          '       command="load|dump|delete"\n'
                          '       ns="namespace">\n'
                          '</rosparam>')

    def _on_add_arg_tag_default(self):
        self._insert_text('<arg name="foo" default="1" />')

    def _on_add_arg_tag_value(self):
        self._insert_text('<arg name="foo" value="bar" />')

    def _on_add_test_tag(self):
        dia = PackageDialog()
        if dia.exec_():
            self._insert_text('<test name="%s" pkg="%s" type="%s" test-name="test_%s">\n'
                              '</test>' % (dia.binary, dia.package, dia.binary, dia.binary))

    def _on_add_test_tag_all(self):
        dia = PackageDialog()
        if dia.exec_():
            self._insert_text('<test name="%s" pkg="%s" type="%s" test-name="test_%s">\n'
                              '      args="arg1" time-limit="60.0"\n'
                              '      ns="foo" clear_params="true|false"\n'
                              '      cwd="ROS_HOME|node" retry="0"\n'
                              '      launch-prefix="prefix arguments">\n'
                              '</test>' % (dia.binary, dia.package, dia.binary, dia.binary))
Exemple #59
0
class LevelSelectorPlugin(Plugin):

    def __init__(self, context):
        super(LevelSelectorPlugin, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName('LevelSelectorPlugin')

        # Create QWidget
        self._widget = QWidget()
        # self._widget.setFont(QFont("Times", 15, QFont.Bold))
        self._button_layout = QVBoxLayout(self._widget)

        self.buttons = []
        self.text_label = QLabel("Waiting for MultiLevelMapData...", self._widget)
        self._button_layout.addWidget(self.text_label)

        self._widget.setObjectName('LevelSelectorPluginUI')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number()))
        context.add_widget(self._widget)

        self.connect(self._widget, SIGNAL("update_buttons"), self.update_buttons)
        self.connect(self._widget, SIGNAL("update_button_status"), self.update_button_status)

        # Subcribe to the multi level map data to get information about all the maps.
        self.multimap_subscriber = rospy.Subscriber("map_metadata", MultiLevelMapData, self.process_multimap)
        self.levels = []
        self.current_level = None

        # Subscribe to the current level we are on.
        self.status_subscriber = None

        # Create a service proxy to change the current level.
        self.level_selector_proxy = rospy.ServiceProxy("level_mux/change_current_level", ChangeCurrentLevel)
        self.level_selector_proxy.wait_for_service()

    def process_multimap(self, msg):
        self.levels = msg.levels
        self._widget.emit(SIGNAL("update_buttons"))

    def update_buttons(self):
        self.clean()
        for index, level in enumerate(self.levels):
            self.text_label.setText("Choose Level: ")
            button = QPushButton(level.level_id, self._widget)
            button.clicked[bool].connect(self.handle_button)
            button.setCheckable(True)
            self._button_layout.addWidget(button)
            self.buttons.append(button)

        # Subscribe to the current level we are on.
        if self.status_subscriber is None:
            self.status_subscriber = rospy.Subscriber("level_mux/current_level", LevelMetaData, self.process_level_status)

    def update_button_status(self):
        for index, level in enumerate(self.levels):
            if self.current_level == level.level_id:
                self.buttons[index].setChecked(True)
            else:
                self.buttons[index].setChecked(False)

    def process_level_status(self, msg):
        level_found = False
        for level in self.levels:
            if msg.level_id == level.level_id:
                self.current_level = level.level_id
                level_found = True
                break
        if not level_found:
            self.current_level = None
        self._widget.emit(SIGNAL("update_button_status"))

    def handle_button(self):
        source = self.sender()

        if source.text() == self.current_level:
            source.setChecked(True)
            return

        # Construct a identity pose. The level selector cannot be used to choose the initialpose, as it does not have
        # the interface for specifying the position. The position should be specified via rviz.
        origin_pose = PoseWithCovarianceStamped()
        origin_pose.header.frame_id = frameIdFromLevelId(source.text())
        origin_pose.pose.pose.orientation.w = 1    # Makes the origin quaternion valid.
        origin_pose.pose.covariance[0] = 1.0
        origin_pose.pose.covariance[7] = 1.0
        origin_pose.pose.covariance[14] = 1.0
        origin_pose.pose.covariance[21] = 1.0
        origin_pose.pose.covariance[28] = 1.0
        origin_pose.pose.covariance[35] = 1.0

        # Don't actually publish the initial pose via the level selector. It doesn't know any better.
        self.level_selector_proxy(source.text(), False, origin_pose)

    def clean(self):
        while self._button_layout.count():
            item = self._button_layout.takeAt(0)
            item.widget().deleteLater()

    def save_settings(self, plugin_settings, instance_settings):
        pass

    def restore_settings(self, plugin_settings, instance_settings):
        pass