def glview_mouseReleaseEvent(self, event):
     if event.button() == Qt.RightButton:
         menu = QMenu(self._glview)
         action = QAction(self._glview.tr("Reset view"), self._glview)
         menu.addAction(action)
         action.triggered.connect(self.set_default_view)
         menu.exec_(self._glview.mapToGlobal(event.pos()))
Exemplo n.º 2
0
    def on_ctrl_list_tree_widget_customContextMenuRequested(self, pos):
        ctrlman_ns = self.cm_namespace_combo.currentText()
        item = self.ctrl_list_tree_widget.itemAt(pos)
        if item is None:
            return
        ctrl_name = item.data(0, Qt.UserRole)
        ctrl_state = self._ctrlers[ctrl_name]['state']

        # show context menu
        menu = QMenu(self)
        if ctrl_state == 'running':
            action_stop = menu.addAction(
                    QIcon.fromTheme('media-playback-stop'), 'Stop Controller')
            action_kill = menu.addAction(
                    QIcon.fromTheme('list-remove'), 'Stop and Unload Controller')
        elif ctrl_state == 'stopped':
            action_start = menu.addAction(
                    QIcon.fromTheme('media-playback-start'), 'Start Controller')
            action_unload = menu.addAction(
                    QIcon.fromTheme('list-remove'), 'Unload Controller')

        action = menu.exec_(self.ctrl_list_tree_widget.mapToGlobal(pos))

        # evaluate user action
        if ctrl_state == 'running':
            if action is action_stop:
                self.start_stop_controller(ctrlman_ns, ctrl_name, False)
            elif action is action_kill:
                self.start_stop_controller(ctrlman_ns, ctrl_name, False)
                self.unload_controller(ctrlman_ns, ctrl_name)
        elif ctrl_state == 'stopped':
            if action is action_start:
                self.start_stop_controller(ctrlman_ns, ctrl_name, True)
            elif action is action_unload:
                self.unload_controller(ctrlman_ns, ctrl_name)
    def handle_header_view_customContextMenuRequested(self, pos):

        # create context menu
        menu = QMenu(self)

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

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

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

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

        elif action is action_toggle_sorting:
            self.setSortingEnabled(not self.isSortingEnabled())
 def contextMenuEvent(self, event):
     menu = QMenu()
     clip = menu.addAction('clip')
     clip.setEnabled(False)
     menu.addSeparator()
     remove = menu.addAction('remove clip')
     result = menu.exec_(event.screenPos())
     if result == remove:
         self.scene().removeItem(self)
    def _open_context_menu(self, position):
        indexes = self.plugin_manager_widget.plugin_tree_view.selectedIndexes()
        level = -1
        if len(indexes) > 0:
            level = 0
            index = indexes[0]
            while index.parent().isValid():
                index = index.parent()
                level += 1

        menu = QMenu()
        if level == 0:
            expand_action = QAction(self.tr('Expand'), None)
            expand_action.triggered.connect(self.plugin_manager_widget.plugin_tree_view.expandAll)
            menu.addAction(expand_action)
        if level == 0 or level == 1:
            remove_action = QAction(self.tr('Remove'), None)
            remove_action.triggered.connect(self.remove_plugins)
            menu.addAction(remove_action)

        menu.exec_(self.plugin_manager_widget.plugin_tree_view.viewport().mapToGlobal(position))
Exemplo n.º 6
0
    def handle_header_view_customContextMenuRequested(self, pos):
        header = self.topics_tree_widget.header()

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

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

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

        # Evaluate user action
        if action is action_toggle_auto_resize:
            if header.resizeMode(0) == QHeaderView.ResizeToContents:
                header.setResizeMode(QHeaderView.Interactive)
            else:
                header.setResizeMode(QHeaderView.ResizeToContents)
Exemplo n.º 8
0
 def eventFilter(self, obj, event):
     if event.type() in self._event_callbacks:
         ret_val = self._event_callbacks[event.type()](obj, event)
         if ret_val is not None:
             return ret_val
     if event.type() == event.ContextMenu and obj == self.title_label:
         menu = QMenu(self)
         rename_action = menu.addAction(self.tr('Rename dock widget'))
         action = menu.exec_(self.mapToGlobal(event.pos()))
         if action == rename_action:
             self.title_label.hide()
             self.title_edit.setText(self.title_label.text())
             self.title_edit.show()
             self.title_edit.setFocus()
         return True
     return QObject.eventFilter(self, obj, event)
    def _rightclick_menu(self, event):
        """
        :type event: QEvent
        """

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

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

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

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

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

                else:
                    raise
            except rosmsg.ROSMsgException, e:
                QMessageBox.warning(self, self.tr('Warning'),
                                    self.tr('The selected item component ' +
                                            'does not have text to view.'))
            if browsetext is not None:
                self._browsers.append(TextBrowseDialog(browsetext,
                                                       self._rospack))
                self._browsers[-1].show()
    def _add_exclude_filter(self, filter_index=False):
        """
        :param filter_index: if false then this function shows a QMenu to allow the user to choose a type of message filter. ''bool''
        OR
        :param filter_index: the index of the filter to be added, ''int''
        :return: if a filter was added then the index is returned, ''int''
        OR
        :return: if no filter was added then None is returned, ''NoneType''
        """
        if filter_index is False:
            filter_index = -1
            filter_select_menu = QMenu()
            for index in self._filter_factory_order:
                # flattens the _exclude filters list and only adds the item if it doesn't already exist
                if index in ['message', 'location'] or not self.filter_factory[index][1] in [type(item) for sublist in self._exclude_filters for item in sublist]:
                    filter_select_menu.addAction(self.filter_factory[index][0])
            action = filter_select_menu.exec_(QCursor.pos())
            if action is None:
                return None
            for index in self._filter_factory_order:
                if self.filter_factory[index][0] == action.text():
                    filter_index = index
            if filter_index == -1:
                return None

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

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

        # place the widget in the proper location
        self.exclude_table.insertRow(index)
        self.exclude_table.setCellWidget(index, 0, self._exclude_filters[index][1])
        self.exclude_table.resizeColumnsToContents()
        self.exclude_table.resizeRowsToContents()
        newfilter.filter_changed_signal.emit()
        return index
    def _show_context_menu(self, item, global_pos):
        if item is None:
            return

        # show context menu
        menu = QMenu(self)
        action_item_expand = menu.addAction(QIcon.fromTheme('zoom-in'), "Expand All Children")
        action_item_collapse = menu.addAction(QIcon.fromTheme('zoom-out'), "Collapse All Children")
        action = menu.exec_(global_pos)

        # evaluate user action
        if action in (action_item_expand, action_item_collapse):
            expanded = (action is action_item_expand)

            def recursive_set_expanded(item):
                item.setExpanded(expanded)
                for index in range(item.childCount()):
                    recursive_set_expanded(item.child(index))
            recursive_set_expanded(item)
Exemplo n.º 12
0
    def _on_ctrl_menu(self, pos):
        # Get data of selected controller
        row = self._widget.table_view.rowAt(pos.y())
        if row < 0:
            return  # Cursor is not under a valid item

        ctrl = self._controllers[row]

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

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

        # Evaluate user action
        if ctrl.state == 'running':
            if action is action_stop:
                self._stop_controller(ctrl.name)
            elif action is action_kill:
                self._stop_controller(ctrl.name)
                self._unload_controller(ctrl.name)
        elif ctrl.state == 'stopped':
            if action is action_start:
                self._start_controller(ctrl.name)
            elif action is action_unload:
                self._unload_controller(ctrl.name)
        elif ctrl.state == 'uninitialized':
            if action is action_load:
                self._load_controller(ctrl.name)
            if action is action_spawn:
                self._load_controller(ctrl.name)
                self._start_controller(ctrl.name)
    def contextMenuEvent(self, event):
        menu = QMenu()
        clip = menu.addAction('track')
        clip.setEnabled(False)
        menu.addSeparator()
        copy_to = {}
        for destination_track in self.scene().tracks(self._type):
            if destination_track is not self:
                copy_to[menu.addAction('copy track to "%s"' % destination_track.name())] = destination_track
        clear = menu.addAction('clear track')

        result = menu.exec_(event.screenPos())
        if result == clear:
            self.clear()
        elif result in copy_to:
            destination_track = copy_to[result]
            destination_track.clear()
            for clip in self.clips():
                destination_track.add_clip(clip.text(), clip.starttime(), clip.duration(), clip.data())
Exemplo n.º 14
0
    def on_topics_tree_widget_customContextMenuRequested(self, pos):
        item = self.topics_tree_widget.itemAt(pos)
        if item is None:
            return

        # show context menu
        menu = QMenu(self)
        action_item_expand = menu.addAction(QIcon.fromTheme('zoom-in'), 'Expand All Children')
        action_item_collapse = menu.addAction(QIcon.fromTheme('zoom-out'), 'Collapse All Children')
        action = menu.exec_(self.topics_tree_widget.mapToGlobal(pos))

        # evaluate user action
        if action in (action_item_expand, action_item_collapse):
            expanded = (action is action_item_expand)

            def recursive_set_expanded(item):
                item.setExpanded(expanded)
                for index in range(item.childCount()):
                    recursive_set_expanded(item.child(index))
            recursive_set_expanded(item)
    def positions_list_context_menu(self, group_type, pos):
        list_widget = self.list_widgets[group_type]
        list_item = list_widget.itemAt(pos)
        if list_item is None:
            return

        menu = QMenu()
        move_to = {}
        for group in self.robot_config.group_list():
            if list_item._type == group.group_type:
                move_to[menu.addAction('move "%s"' % group.name)] = [group.name]
        # move_to[menu.addAction('move all')] = list(move_to.itervalues())
        move_to[menu.addAction('move all')] = [group_list[0] for group_list in list(move_to.itervalues())]
        result = menu.exec_(list_widget.mapToGlobal(pos))
        if result in move_to:
            group_names = move_to[result]
            for group_name in group_names:
                target_positions = self.robot_config.groups[group_name].adapt_to_side(list_item._data)
                self._motion_publisher.move_to_position(group_name, target_positions, self.time_factor_spin.value())
                print '[Motion Editor] Moving %s to: %s' % (group_name, zip(self.robot_config.groups[group_name].joints_sorted(), target_positions))
Exemplo n.º 16
0
 def eventFilter(self, obj, event):
     if event.type() in self._event_callbacks:
         ret_val = self._event_callbacks[event.type()](obj, event)
         if ret_val is not None:
             return ret_val
     if event.type() == event.ContextMenu and obj == self.title_label:
         menu = QMenu(self)
         rename_action = menu.addAction(self.tr('Rename dock widget'))
         hide_action = QAction("Hide title bar", self)
         hide_action.setCheckable(True)
         hide_action.setChecked(self.hide_title_bar)
         if self._dock_widget.features() & QDockWidget.DockWidgetFloatable and \
                 self._dock_widget.features() & QDockWidget.DockWidgetMovable:
             menu.addAction(hide_action)
         action = menu.exec_(self.mapToGlobal(event.pos()))
         if action == rename_action:
             self.title_label.hide()
             self.title_edit.setText(self.title_label.text())
             self.title_edit.show()
             self.title_edit.setFocus()
         if action == hide_action:
             self.hide_title_bar = not self.hide_title_bar
         return True
     return QObject.eventFilter(self, obj, event)
 def handle_customContextMenuRequested(self, pos):
     # show context menu
     menu = QMenu(self)
     self._context_menu_add_actions(menu, pos)
     menu.exec_(self.mapToGlobal(pos))
Exemplo n.º 18
0
class EditorWidget(QWidget):
    '''
    This class is abstract -- its child classes should be instantiated.

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

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

        super(EditorWidget, self).__init__()

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

        self.old_value = None

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

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

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

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

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

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

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

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

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

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

    def contextMenuEvent(self, e):
        self.cmenu.exec_(e.globalPos())
Exemplo n.º 19
0
    def _rightclick_menu(self, event):
        """
        Dynamically builds the rightclick menu based on the unique column data
        from the passed in datamodel and then launches it modally
        :param event: the mouse event object, ''QMouseEvent''
        """
        severities = self._datamodel.get_unique_col_data(1)
        nodes = self._datamodel.get_unique_col_data(2)
        topics = self._datamodel.get_unique_col_data(4)
        temp = []
        for topic in topics:
            if topic.find(', ') == -1:
                temp.append(topic)
            else:
                temp = temp + topic.split(', ')
        topics = list(set(temp))

        columns = list(self._datamodel.message_members())
        for index in range(len(columns)):
            columns[index] = [columns[index][1:].capitalize()]

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

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

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

            if roottitle == self.tr('Highlight'):
                self._process_highlight_exclude_filter(
                    action.text(),
                    action.parentWidget().title(), False)
            elif roottitle == self.tr('Exclude'):
                self._process_highlight_exclude_filter(
                    action.text(),
                    action.parentWidget().title(), True)
            else:
                raise RuntimeError(
                    "Unknown Root Action %s selected in ConsoleWidget._rightclick_menu()"
                    % roottitle)
        self.update_status()
    def _rightclick_menu(self, event):
        """
        Dynamically builds the rightclick menu based on the unique column data
        from the passed in datamodel and then launches it modally
        :param event: the mouse event object, ''QMouseEvent''
        """
        severities = {}
        for severity, label in Message.SEVERITY_LABELS.items():
            if severity in self._model.get_unique_severities():
                severities[severity] = label
        nodes = sorted(self._model.get_unique_nodes())
        topics = sorted(self._model.get_unique_topics())

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

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

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

            if roottitle == self.tr('Highlight'):
                self._process_highlight_exclude_filter(action.text(), action.parentWidget().title(), False)
            elif roottitle == self.tr('Exclude'):
                self._process_highlight_exclude_filter(action.text(), action.parentWidget().title(), True)
            else:
                raise RuntimeError("Unknown Root Action %s selected in ConsoleWidget._rightclick_menu()" % roottitle)
    def _add_highlight_filter(self, filter_index=False):
        """
        :param filter_index: if false then this function shows a QMenu to allow the user to choose a type of message filter. ''bool''
        OR
        :param filter_index: the index of the filter to be added, ''int''
        :return: if a filter was added then the index is returned, ''int''
        OR
        :return: if no filter was added then None is returned, ''NoneType''
        """
        if filter_index is False:
            filter_index = -1
            filter_select_menu = QMenu()
            for index in self._filter_factory_order:
                # flattens the _highlight filters list and only adds the item if it doesn't already exist
                if index in ['message', 'location'
                             ] or not self.filter_factory[index][1] in [
                                 type(item)
                                 for sublist in self._highlight_filters
                                 for item in sublist
                             ]:
                    filter_select_menu.addAction(self.filter_factory[index][0])
            action = filter_select_menu.exec_(QCursor.pos())
            if action is None:
                return
            for index in self._filter_factory_order:
                if self.filter_factory[index][0] == action.text():
                    filter_index = index
            if filter_index == -1:
                return

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

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

        # place the widget in the proper location
        self.highlight_table.insertRow(index)
        self.highlight_table.setCellWidget(index, 0,
                                           self._highlight_filters[index][1])
        self.highlight_table.resizeColumnsToContents()
        self.highlight_table.resizeRowsToContents()
        newfilter.filter_changed_signal.emit()
        return index