Exemple #1
0
class XUrlWidget(QWidget):
    urlChanged = qt.Signal(str)
    urlEdited = qt.Signal()

    def __init__(self, parent):
        super(XUrlWidget, self).__init__(parent)

        # define the interface
        self._urlEdit = XLineEdit(self)
        self._urlButton = QToolButton(self)

        self._urlButton.setAutoRaise(True)
        self._urlButton.setIcon(QIcon(resources.find('img/web.png')))
        self._urlButton.setToolTip('Browse Link')
        self._urlButton.setFocusPolicy(Qt.NoFocus)

        self._urlEdit.setHint('http://')

        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self._urlEdit)
        layout.addWidget(self._urlButton)

        self.setLayout(layout)
        self.setFocusPolicy(Qt.StrongFocus)

        # create connections
        self._urlEdit.textChanged.connect(self.urlChanged)
        self._urlEdit.textEdited.connect(self.urlEdited)
        self._urlButton.clicked.connect(self.browse)

    def blockSignals(self, state):
        """
        Blocks the signals for this widget and its sub-parts.
        
        :param      state | <bool>
        """
        super(XUrlWidget, self).blockSignals(state)
        self._urlEdit.blockSignals(state)
        self._urlButton.blockSignals(state)

    def browse(self):
        """
        Brings up a web browser with the address in a Google map.
        """
        webbrowser.open(self.url())

    def hint(self):
        """
        Returns the hint associated with this widget.
        
        :return     <str>
        """
        return self._urlEdit.hint()

    def lineEdit(self):
        """
        Returns the line edit linked with this widget.
        
        :return     <XLineEdit>
        """
        return self._urlEdit

    def setFocus(self):
        """
        Sets the focus for this widget on its line edit.
        """
        self._urlEdit.setFocus()

    @qt.Slot(str)
    def setHint(self, hint):
        """
        Sets the hint associated with this widget.
        
        :param      hint | <str>
        """
        self._urlEdit.setHint(hint)

    @qt.Slot(str)
    def setUrl(self, url):
        """
        Sets the url for this widget to the inputed url.
        
        :param      url | <str>
        """
        self._urlEdit.setText(str(url))

    def url(self):
        """
        Returns the current url from the edit.
        
        :return     <str>
        """
        return str(self._urlEdit.text())

    x_hint = qt.Property(str, hint, setHint)
    x_url = qt.Property(str, url, setUrl)
class XFindWidget(QWidget):
    """ """
    __designer_icon__ = resources.find('img/search.png')

    def __init__(self, parent=None):
        super(XFindWidget, self).__init__(parent)

        # define custom properties
        self._textEdit = None
        self._webView = None
        self._lastCursor = QTextCursor()
        self._lastText = ''

        self._closeButton = QToolButton(self)
        self._closeButton.setIcon(QIcon(resources.find('img/close.png')))
        self._closeButton.setAutoRaise(True)
        self._closeButton.setToolTip('Hide the Find Field.')

        self._searchEdit = XLineEdit(self)
        self._searchEdit.setHint('search for...')

        self._previousButton = QToolButton(self)
        self._previousButton.setIcon(QIcon(resources.find('img/back.png')))
        self._previousButton.setAutoRaise(True)
        self._previousButton.setToolTip('Find Previous')

        self._nextButton = QToolButton(self)
        self._nextButton.setIcon(QIcon(resources.find('img/forward.png')))
        self._nextButton.setAutoRaise(True)
        self._nextButton.setToolTip('Find Next')

        self._caseSensitiveCheckbox = QCheckBox(self)
        self._caseSensitiveCheckbox.setText('Case Sensitive')

        self._wholeWordsCheckbox = QCheckBox(self)
        self._wholeWordsCheckbox.setText('Whole Words Only')

        self._regexCheckbox = QCheckBox(self)
        self._regexCheckbox.setText('Use Regex')

        self._findAction = QAction(self)
        self._findAction.setText('Find...')
        self._findAction.setIcon(QIcon(resources.find('img/search.png')))
        self._findAction.setToolTip('Find in Text')
        self._findAction.setShortcut(QKeySequence('Ctrl+F'))
        self._findAction.setShortcutContext(Qt.WidgetWithChildrenShortcut)

        # layout the widgets
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self._closeButton)
        layout.addWidget(self._searchEdit)
        layout.addWidget(self._previousButton)
        layout.addWidget(self._nextButton)
        layout.addWidget(self._caseSensitiveCheckbox)
        layout.addWidget(self._wholeWordsCheckbox)
        layout.addWidget(self._regexCheckbox)

        self.setLayout(layout)

        # create connections
        self._findAction.triggered.connect(self.show)
        self._searchEdit.textChanged.connect(self.findNext)
        self._closeButton.clicked.connect(self.hide)
        self._previousButton.clicked.connect(self.findPrev)
        self._nextButton.clicked.connect(self.findNext)
        self._caseSensitiveCheckbox.clicked.connect(self.findNext)
        self._wholeWordsCheckbox.clicked.connect(self.findNext)
        self._searchEdit.returnPressed.connect(self.findNext)
        self._regexCheckbox.clicked.connect(self.findNext)

    def find(self, flags=0):
        """
        Looks throught the text document based on the current criteria.  The \
        inputed flags will be merged with the generated search flags.
        
        :param      flags | <QTextDocument.FindFlag>
        
        :return     <bool> | success
        """
        # check against the web and text views
        if (not (self._textEdit or self._webView)):
            fg = QColor('darkRed')
            bg = QColor('red').lighter(180)

            palette = self.palette()
            palette.setColor(palette.Text, fg)
            palette.setColor(palette.Base, bg)

            self._searchEdit.setPalette(palette)
            self._searchEdit.setToolTip('No Text Edit is linked.')

            return False

        if (self._caseSensitiveCheckbox.isChecked()):
            flags |= QTextDocument.FindCaseSensitively

        if (self._textEdit and self._wholeWordsCheckbox.isChecked()):
            flags |= QTextDocument.FindWholeWords

        terms = self._searchEdit.text()
        if (terms != self._lastText):
            self._lastCursor = QTextCursor()

        if (self._regexCheckbox.isChecked()):
            terms = QRegExp(terms)

        palette = self.palette()

        # search on a text edit
        if (self._textEdit):
            cursor = self._textEdit.document().find(
                terms, self._lastCursor, QTextDocument.FindFlags(flags))
            found = not cursor.isNull()
            self._lastCursor = cursor
            self._textEdit.setTextCursor(cursor)

        elif (QWebPage):
            flags = QWebPage.FindFlags(flags)
            flags |= QWebPage.FindWrapsAroundDocument

            found = self._webView.findText(terms, flags)

        self._lastText = self._searchEdit.text()

        if (not terms or found):
            fg = palette.color(palette.Text)
            bg = palette.color(palette.Base)
        else:
            fg = QColor('darkRed')
            bg = QColor('red').lighter(180)

        palette.setColor(palette.Text, fg)
        palette.setColor(palette.Base, bg)

        self._searchEdit.setPalette(palette)

        return found

    def findNext(self):
        """
        Looks for the search terms that come up next based on the criteria.
        
        :return     <bool> | success
        """
        return self.find()

    def findPrev(self):
        """
        Looks for the search terms that come up last based on the criteria.
        
        :return     <bool> | success
        """
        return self.find(QTextDocument.FindBackward)

    def setTextEdit(self, textEdit):
        """
        Sets the text edit that this find widget will use to search.
        
        :param      textEdit | <QTextEdit>
        """
        if (self._textEdit):
            self._textEdit.removeAction(self._findAction)

        self._textEdit = textEdit
        if (textEdit):
            textEdit.addAction(self._findAction)

    def setWebView(self, webView):
        """
        Sets the web view edit that this find widget will use to search.
        
        :param      webView | <QWebView>
        """
        if (self._webView):
            self._webView.removeAction(self._findAction)

        self._webView = webView
        if (webView):
            webView.addAction(self._findAction)

    def show(self):
        """
        Sets this widget visible and then makes the find field have focus.
        """
        super(XFindWidget, self).show()

        self._searchEdit.setFocus()

    def textEdit(self):
        """
        Returns the text edit linked with this find widget.
        
        :return     <QTextEdit>
        """
        return self._textEdit

    def webView(self):
        """
        Returns the text edit linked with this find widget.
        
        :return     <QWebView>
        """
        return self._webView
Exemple #3
0
class XSearchActionWidget(QWidget):
    def __init__(self, parent, action):
        super(XSearchActionWidget, self).__init__(parent)
        
        # define custom properties
        self._initialized = False
        self._triggerText = ''
        
        # define the interface
        self._searchEdit = XLineEdit(self)
        self._searchEdit.setIcon(QIcon(resources.find('img/search.png')))
        self._searchEdit.setHint('enter search')
        self._searchEdit.setFixedHeight(24)
        
        # define the completer
        self._completer = XTreeWidget(self)
        self._completer.setHint('No actions were found.')
        self._completer.setWindowFlags(Qt.Popup)
        self._completer.setRootIsDecorated(False)
        self._completer.header().hide()
        self._completer.setSortingEnabled(True)
        self._completer.sortByColumn(0, Qt.AscendingOrder)
        self._completer.installEventFilter(self)
        self._completer.setFocusProxy(self._searchEdit)
        self._completer.setShowGrid(False)
        self._completer.setFrameShape(XTreeWidget.Box)
        self._completer.setFrameShadow(XTreeWidget.Plain)
        
        # match the look for the completer to the menu
        palette = self._completer.palette()
        palette.setColor(palette.Base, palette.color(palette.Window))
        palette.setColor(palette.Text, palette.color(palette.WindowText))
        palette.setColor(palette.WindowText, palette.color(palette.Mid))
        self._completer.setPalette(palette)
        
        # create the layout
        layout = QHBoxLayout()
        layout.setContentsMargins(4, 4, 4, 4)
        layout.addWidget(self._searchEdit)
        self.setLayout(layout)
        
        # create connections
        self._searchEdit.textChanged.connect(self.filterOptions)
        self._completer.itemClicked.connect(self.triggerItem)
        parent.aboutToShow.connect(self.aboutToShow)
    
    def aboutToShow(self):
        """
        Processes the search widget when the menu is about to show.
        """
        self.clear()
        self._searchEdit.setFocus()
    
    def addItems(self, menus, processed=None):
        """
        Adds items to the completion tree from the menu.
        
        :param      menus | [<QMenu>, ..]
                    procesed | [<QAction>, ..] || None
        """
        if processed is None:
            processed = []
        
        for menu in menus:
            for action in menu.actions():
                # since we can have 1 action in more than 1 submenu, we
                # will want to make sure we're only adding a unique one
                # so we don't have duplicates
                text = nativestring(action.text())
                if text in processed or action.isSeparator():
                    continue
                
                processed.append(text)
                
                if text and unwrapVariant(action.data()) != 'menu':
                    item = XTreeWidgetItem(self._completer, [text])
                    item.setFixedHeight(20)
                    item.setIcon(0, action.icon())
                    item.setToolTip(0, action.toolTip())
                    item.setData(0, Qt.UserRole, wrapVariant(action))
    
    def clear(self):
        """
        Clears the text from the search edit.
        """
        self._searchEdit.blockSignals(True)
        self._searchEdit.setText('')
        self._searchEdit.blockSignals(False)
    
    def completer(self):
        """
        Returns the completion widget for this menu.
        
        :return     <projexui.widgets.xtreewidget.XTreeWidget>
        """
        return self._completer
    
    def eventFilter(self, object, event):
        """
        Listens for the key press event from the tree widget to pass along
        to the line edit.
        
        :param      object | <QWidget>
                    event  | <QEvent>
        
        :return     <bool> | consumed
        """
        if event.type() == event.KeyPress:
            if event.key() == Qt.Key_Escape:
                self._completer.hide()
                self._completer.setCurrentItem(None)

            elif event.key() in (Qt.Key_Enter, Qt.Key_Return):
                tree = self._completer
                item = tree.currentItem() or tree.itemAt(0, 0)
                self.triggerItem(item)

            self._searchEdit.keyPressEvent(event)

        return False

    def filterOptions(self, text):
        """
        Filters the searched actions based on the inputed text.
        
        :param      text | <str>
        """
        if not text:
            self._completer.hide()
            self._completer.setCurrentItem(None)
            return

        # block the signals
        self._completer.setUpdatesEnabled(False)
        self._completer.blockSignals(True)

        # initialize the actions
        menu = self.parent()
        if not self._initialized:
            self.addItems([menu] + menu.findChildren(QMenu))
            self._initialized = True

        # filter the actions in the search view
        visible_count = 0
        item_count = self._completer.topLevelItemCount()
        for i in range(item_count):
            item = self._completer.topLevelItem(i)
            check = nativestring(item.text(0)).lower()
            hidden = not nativestring(text).lower() in check
            item.setHidden(hidden)
            visible_count += 1 if not hidden else 0

        # show the popup widget if it is not visible
        if not self._completer.isVisible():
            point = QPoint(-1, self.height())
            width = menu.width()
            height = menu.height() - self.height() - 1
            height = max(height, 22 * min(visible_count, 5))
            
            self._completer.move(self.mapToGlobal(point))
            self._completer.resize(width, height)
            self._completer.show()

        # restore signals
        self._completer.setUpdatesEnabled(True)
        self._completer.blockSignals(False)

    def searchEdit(self):
        """
        Returns the line edit associated with this widget.
        
        :return     <projexui.widgets.xlineedit.XLineEdit>
        """
        return self._searchEdit
    
    def text(self):
        """
        Returns the text of the item that was triggered.
        
        :return     <str>
        """
        return self._triggerText
    
    def triggerItem(self, item):
        """
        Triggers the item by calling its action's toggled state to display or
        hide the dock panel.
        
        :param      item | <QtGui.QTreeWidgetItem>
        """
        if not item:
            return
        
        # emit the trigger action
        self._triggerText = item.text(0)
        self._completer.hide()
        self._completer.setCurrentItem(None)
        self.parent().hide()
        
        # trigger the action
        unwrapVariant(item.data(0, Qt.UserRole)).trigger()
class XFindWidget(QWidget):
    """ """
    __designer_icon__ = resources.find('img/search.png')
    
    def __init__( self, parent = None ):
        super(XFindWidget, self).__init__( parent )
        
        # define custom properties
        self._textEdit   = None
        self._webView    = None
        self._lastCursor = QTextCursor()
        self._lastText = ''
        
        self._closeButton = QToolButton(self)
        self._closeButton.setIcon(QIcon(resources.find('img/close.png')))
        self._closeButton.setAutoRaise(True)
        self._closeButton.setToolTip('Hide the Find Field.')
        
        self._searchEdit = XLineEdit(self)
        self._searchEdit.setHint('search for...')
        
        self._previousButton = QToolButton(self)
        self._previousButton.setIcon(QIcon(resources.find('img/back.png')))
        self._previousButton.setAutoRaise(True)
        self._previousButton.setToolTip('Find Previous')
        
        self._nextButton = QToolButton(self)
        self._nextButton.setIcon(QIcon(resources.find('img/forward.png')))
        self._nextButton.setAutoRaise(True)
        self._nextButton.setToolTip('Find Next')
        
        self._caseSensitiveCheckbox = QCheckBox(self)
        self._caseSensitiveCheckbox.setText('Case Sensitive')
        
        self._wholeWordsCheckbox = QCheckBox(self)
        self._wholeWordsCheckbox.setText('Whole Words Only')
        
        self._regexCheckbox = QCheckBox(self)
        self._regexCheckbox.setText('Use Regex')
        
        self._findAction = QAction(self)
        self._findAction.setText('Find...')
        self._findAction.setIcon(QIcon(resources.find('img/search.png')))
        self._findAction.setToolTip('Find in Text')
        self._findAction.setShortcut(QKeySequence('Ctrl+F'))
        self._findAction.setShortcutContext(Qt.WidgetWithChildrenShortcut)
        
        # layout the widgets
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget( self._closeButton )
        layout.addWidget( self._searchEdit )
        layout.addWidget( self._previousButton )
        layout.addWidget( self._nextButton )
        layout.addWidget( self._caseSensitiveCheckbox )
        layout.addWidget( self._wholeWordsCheckbox )
        layout.addWidget( self._regexCheckbox )
        
        self.setLayout(layout)
        
        # create connections
        self._findAction.triggered.connect(          self.show )
        self._searchEdit.textChanged.connect(        self.findNext )
        self._closeButton.clicked.connect(           self.hide )
        self._previousButton.clicked.connect(        self.findPrev )
        self._nextButton.clicked.connect(            self.findNext )
        self._caseSensitiveCheckbox.clicked.connect( self.findNext )
        self._wholeWordsCheckbox.clicked.connect(    self.findNext )
        self._searchEdit.returnPressed.connect(      self.findNext )
        self._regexCheckbox.clicked.connect(         self.findNext )
    
    def find( self, flags = 0 ):
        """
        Looks throught the text document based on the current criteria.  The \
        inputed flags will be merged with the generated search flags.
        
        :param      flags | <QTextDocument.FindFlag>
        
        :return     <bool> | success
        """
        # check against the web and text views
        if ( not (self._textEdit or self._webView) ):
            fg = QColor('darkRed')
            bg = QColor('red').lighter(180)
            
            palette = self.palette()
            palette.setColor(palette.Text, fg)
            palette.setColor(palette.Base, bg)
            
            self._searchEdit.setPalette(palette)
            self._searchEdit.setToolTip( 'No Text Edit is linked.' )
            
            return False
        
        if ( self._caseSensitiveCheckbox.isChecked() ):
            flags |= QTextDocument.FindCaseSensitively
        
        if ( self._textEdit and self._wholeWordsCheckbox.isChecked() ):
            flags |= QTextDocument.FindWholeWords
        
        terms = self._searchEdit.text()
        if ( terms != self._lastText ):
            self._lastCursor = QTextCursor()
        
        if ( self._regexCheckbox.isChecked() ):
            terms = QRegExp(terms)
        
        palette = self.palette()
        
        # search on a text edit
        if ( self._textEdit ):
            cursor  = self._textEdit.document().find(terms, 
                                                 self._lastCursor, 
                                                 QTextDocument.FindFlags(flags))
            found   = not cursor.isNull()
            self._lastCursor = cursor
            self._textEdit.setTextCursor(cursor)
        
        elif ( QWebPage ):
            flags = QWebPage.FindFlags(flags)
            flags |= QWebPage.FindWrapsAroundDocument
            
            found = self._webView.findText(terms, flags)
        
        self._lastText = self._searchEdit.text()
        
        if ( not terms or found ):
            fg = palette.color(palette.Text)
            bg = palette.color(palette.Base)
        else:
            fg = QColor('darkRed')
            bg = QColor('red').lighter(180)
        
        palette.setColor(palette.Text, fg)
        palette.setColor(palette.Base, bg)
        
        self._searchEdit.setPalette(palette)
        
        return found
    
    def findNext( self ):
        """
        Looks for the search terms that come up next based on the criteria.
        
        :return     <bool> | success
        """
        return self.find()
    
    def findPrev( self ):
        """
        Looks for the search terms that come up last based on the criteria.
        
        :return     <bool> | success
        """
        return self.find(QTextDocument.FindBackward)
        
    def setTextEdit( self, textEdit ):
        """
        Sets the text edit that this find widget will use to search.
        
        :param      textEdit | <QTextEdit>
        """
        if ( self._textEdit ):
            self._textEdit.removeAction(self._findAction)
            
        self._textEdit = textEdit
        if ( textEdit ):
            textEdit.addAction(self._findAction)
    
    def setWebView( self, webView ):
        """
        Sets the web view edit that this find widget will use to search.
        
        :param      webView | <QWebView>
        """
        if ( self._webView ):
            self._webView.removeAction(self._findAction)
        
        self._webView = webView
        if ( webView ):
            webView.addAction(self._findAction)
    
    def show( self ):
        """
        Sets this widget visible and then makes the find field have focus.
        """
        super(XFindWidget, self).show()
        
        self._searchEdit.setFocus()
    
    def textEdit( self ):
        """
        Returns the text edit linked with this find widget.
        
        :return     <QTextEdit>
        """
        return self._textEdit
    
    def webView( self ):
        """
        Returns the text edit linked with this find widget.
        
        :return     <QWebView>
        """
        return self._webView
Exemple #5
0
class XUrlWidget(QWidget):
    urlChanged = Signal(str)
    urlEdited  = Signal()
    
    def __init__( self, parent ):
        super(XUrlWidget, self).__init__(parent)
        
        # define the interface
        self._urlEdit      = XLineEdit(self)
        self._urlButton    = QToolButton(self)
        
        self._urlButton.setAutoRaise(True)
        self._urlButton.setIcon(QIcon(resources.find('img/web.png')))
        self._urlButton.setToolTip('Browse Link')
        self._urlButton.setFocusPolicy(Qt.NoFocus)
        
        self._urlEdit.setHint('http://')
        
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self._urlEdit)
        layout.addWidget(self._urlButton)
        
        self.setLayout(layout)
        self.setFocusPolicy(Qt.StrongFocus)
        
        # create connections
        self._urlEdit.textChanged.connect(self.urlChanged)
        self._urlEdit.textEdited.connect(self.urlEdited)
        self._urlButton.clicked.connect(self.browse)
    
    def blockSignals( self, state ):
        """
        Blocks the signals for this widget and its sub-parts.
        
        :param      state | <bool>
        """
        super(XUrlWidget, self).blockSignals(state)
        self._urlEdit.blockSignals(state)
        self._urlButton.blockSignals(state)
    
    def browse( self ):
        """
        Brings up a web browser with the address in a Google map.
        """
        webbrowser.open(self.url())
    
    def hint( self ):
        """
        Returns the hint associated with this widget.
        
        :return     <str>
        """
        return self._urlEdit.hint()
    
    def lineEdit( self ):
        """
        Returns the line edit linked with this widget.
        
        :return     <XLineEdit>
        """
        return self._urlEdit
    
    def setFocus(self):
        """
        Sets the focus for this widget on its line edit.
        """
        self._urlEdit.setFocus()
    
    @Slot(str)
    def setHint( self, hint ):
        """
        Sets the hint associated with this widget.
        
        :param      hint | <str>
        """
        self._urlEdit.setHint(hint)
    
    @Slot(str)
    def setUrl( self, url ):
        """
        Sets the url for this widget to the inputed url.
        
        :param      url | <str>
        """
        self._urlEdit.setText(nativestring(url))
    
    def url( self ):
        """
        Returns the current url from the edit.
        
        :return     <str>
        """
        return nativestring(self._urlEdit.text())
    
    x_hint   = Property(str, hint, setHint)
    x_url    = Property(str, url, setUrl)
Exemple #6
0
class XSearchActionWidget(QWidget):
    def __init__(self, parent, action):
        super(XSearchActionWidget, self).__init__(parent)

        # define custom properties
        self._initialized = False
        self._triggerText = ''

        # define the interface
        self._searchEdit = XLineEdit(self)
        self._searchEdit.setIcon(QIcon(resources.find('img/search.png')))
        self._searchEdit.setHint('enter search')
        self._searchEdit.setFixedHeight(24)

        # define the completer
        self._completer = XTreeWidget(self)
        self._completer.setHint('No actions were found.')
        self._completer.setWindowFlags(Qt.Popup)
        self._completer.setRootIsDecorated(False)
        self._completer.header().hide()
        self._completer.setSortingEnabled(True)
        self._completer.sortByColumn(0, Qt.AscendingOrder)
        self._completer.installEventFilter(self)
        self._completer.setFocusProxy(self._searchEdit)
        self._completer.setShowGrid(False)
        self._completer.setFrameShape(XTreeWidget.Box)
        self._completer.setFrameShadow(XTreeWidget.Plain)

        # match the look for the completer to the menu
        palette = self._completer.palette()
        palette.setColor(palette.Base, palette.color(palette.Window))
        palette.setColor(palette.Text, palette.color(palette.WindowText))
        palette.setColor(palette.WindowText, palette.color(palette.Mid))
        self._completer.setPalette(palette)

        # create the layout
        layout = QHBoxLayout()
        layout.setContentsMargins(4, 4, 4, 4)
        layout.addWidget(self._searchEdit)
        self.setLayout(layout)

        # create connections
        self._searchEdit.textChanged.connect(self.filterOptions)
        self._completer.itemClicked.connect(self.triggerItem)
        parent.aboutToShow.connect(self.aboutToShow)

    def aboutToShow(self):
        """
        Processes the search widget when the menu is about to show.
        """
        self.clear()
        self._searchEdit.setFocus()

    def addItems(self, menus, processed=None):
        """
        Adds items to the completion tree from the menu.
        
        :param      menus | [<QMenu>, ..]
                    procesed | [<QAction>, ..] || None
        """
        if processed is None:
            processed = []

        for menu in menus:
            for action in menu.actions():
                # since we can have 1 action in more than 1 submenu, we
                # will want to make sure we're only adding a unique one
                # so we don't have duplicates
                text = nativestring(action.text())
                if text in processed or action.isSeparator():
                    continue

                processed.append(text)

                if text and unwrapVariant(action.data()) != 'menu':
                    item = XTreeWidgetItem(self._completer, [text])
                    item.setFixedHeight(20)
                    item.setIcon(0, action.icon())
                    item.setToolTip(0, action.toolTip())
                    item.setData(0, Qt.UserRole, wrapVariant(action))

    def clear(self):
        """
        Clears the text from the search edit.
        """
        self._searchEdit.blockSignals(True)
        self._searchEdit.setText('')
        self._searchEdit.blockSignals(False)

    def completer(self):
        """
        Returns the completion widget for this menu.
        
        :return     <projexui.widgets.xtreewidget.XTreeWidget>
        """
        return self._completer

    def eventFilter(self, object, event):
        """
        Listens for the key press event from the tree widget to pass along
        to the line edit.
        
        :param      object | <QWidget>
                    event  | <QEvent>
        
        :return     <bool> | consumed
        """
        if event.type() == event.KeyPress:
            if event.key() == Qt.Key_Escape:
                self._completer.hide()
                self._completer.setCurrentItem(None)

            elif event.key() in (Qt.Key_Enter, Qt.Key_Return):
                tree = self._completer
                item = tree.currentItem() or tree.itemAt(0, 0)
                self.triggerItem(item)

            self._searchEdit.keyPressEvent(event)

        return False

    def filterOptions(self, text):
        """
        Filters the searched actions based on the inputed text.
        
        :param      text | <str>
        """
        if not text:
            self._completer.hide()
            self._completer.setCurrentItem(None)
            return

        # block the signals
        self._completer.setUpdatesEnabled(False)
        self._completer.blockSignals(True)

        # initialize the actions
        menu = self.parent()
        if not self._initialized:
            self.addItems([menu] + menu.findChildren(QMenu))
            self._initialized = True

        # filter the actions in the search view
        visible_count = 0
        item_count = self._completer.topLevelItemCount()
        for i in range(item_count):
            item = self._completer.topLevelItem(i)
            check = nativestring(item.text(0)).lower()
            hidden = not nativestring(text).lower() in check
            item.setHidden(hidden)
            visible_count += 1 if not hidden else 0

        # show the popup widget if it is not visible
        if not self._completer.isVisible():
            point = QPoint(-1, self.height())
            width = menu.width()
            height = menu.height() - self.height() - 1
            height = max(height, 22 * min(visible_count, 5))

            self._completer.move(self.mapToGlobal(point))
            self._completer.resize(width, height)
            self._completer.show()

        # restore signals
        self._completer.setUpdatesEnabled(True)
        self._completer.blockSignals(False)

    def searchEdit(self):
        """
        Returns the line edit associated with this widget.
        
        :return     <projexui.widgets.xlineedit.XLineEdit>
        """
        return self._searchEdit

    def text(self):
        """
        Returns the text of the item that was triggered.
        
        :return     <str>
        """
        return self._triggerText

    def triggerItem(self, item):
        """
        Triggers the item by calling its action's toggled state to display or
        hide the dock panel.
        
        :param      item | <QtGui.QTreeWidgetItem>
        """
        if not item:
            return

        # emit the trigger action
        self._triggerText = item.text(0)
        self._completer.hide()
        self._completer.setCurrentItem(None)
        self.parent().hide()

        # trigger the action
        unwrapVariant(item.data(0, Qt.UserRole)).trigger()