Esempio n. 1
0
 def __init__( self, parent = None ):
     super(XKeyValueDialog, self).__init__(parent)
     
     # create the interface
     self._keyEdit   = XLineEdit(self)
     self._keyEdit.setMaximumWidth(80)
     self._keyEdit.setHint( 'set key' )
     
     self._valueEdit = XLineEdit(self)
     self._valueEdit.setHint( 'set value' )
     
     hbox = QHBoxLayout()
     hbox.addWidget(self._keyEdit)
     hbox.addWidget(self._valueEdit)
     
     opts    = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
     buttons = QDialogButtonBox( opts, Qt.Horizontal, self )
     
     vbox = QVBoxLayout()
     vbox.addLayout(hbox)
     vbox.addWidget(buttons)
     
     # update the look and size
     self.setLayout(vbox)
     self.setWindowTitle('Edit Pair')
     self.setMinimumWidth(350)
     self.adjustSize()
     self.setFixedHeight(self.height())
     
     # create connections
     buttons.accepted.connect( self.accept )
     buttons.rejected.connect( self.reject )
Esempio n. 2
0
    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)
Esempio n. 3
0
    def __init__(self, parent):
        super(XLocationWidget, self).__init__(parent)

        # define the interface
        self._locationEdit = XLineEdit(self)
        self._locationButton = QToolButton(self)
        self._urlTemplate = 'http://maps.google.com/maps?%(params)s'
        self._urlQueryKey = 'q'

        self._locationButton.setAutoRaise(True)
        self._locationButton.setIcon(QIcon(resources.find('img/map.png')))

        self._locationEdit.setHint('no location set')

        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self._locationEdit)
        layout.addWidget(self._locationButton)

        self.setLayout(layout)

        # create connections
        self._locationEdit.textChanged.connect(self.locationChanged)
        self._locationEdit.textEdited.connect(self.locationEdited)
        self._locationButton.clicked.connect(self.browseMaps)
Esempio n. 4
0
 def __init__( self, parent ):
     super(XLocationWidget, self).__init__(parent)
     
     # define the interface
     self._locationEdit      = XLineEdit(self)
     self._locationButton    = QToolButton(self)
     self._urlTemplate       = 'http://maps.google.com/maps?%(params)s'
     self._urlQueryKey       = 'q'
     
     self._locationButton.setAutoRaise(True)
     self._locationButton.setIcon(QIcon(resources.find('img/map.png')))
     
     self._locationEdit.setHint('no location set')
     
     layout = QHBoxLayout()
     layout.setContentsMargins(0, 0, 0, 0)
     layout.setSpacing(0)
     layout.addWidget(self._locationEdit)
     layout.addWidget(self._locationButton)
     
     self.setLayout(layout)
     
     # create connections
     self._locationEdit.textChanged.connect(self.locationChanged)
     self._locationEdit.textEdited.connect(self.locationEdited)
     self._locationButton.clicked.connect(self.browseMaps)
Esempio n. 5
0
 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)
Esempio n. 6
0
 def __init__( self, parent = None ):
     super(XFilepathEdit, self).__init__( parent )
     
     # define custom properties
     self._validated         = False
     self._validForeground   = QColor(0, 120, 0)
     self._validBackground   = QColor(0, 120, 0, 100)
     self._invalidForeground = QColor(255, 0, 0)
     self._invalidBackground = QColor(255, 0, 0, 100)
     self._normalizePath     = False
     
     self._filepathMode      = XFilepathEdit.Mode.OpenFile
     self._filepathEdit      = XLineEdit(self)
     self._filepathButton    = QToolButton(self)
     self._filepathTypes     = 'All Files (*.*)'
     
     # set default properties
     ico = projexui.resources.find('img/folder.png')
     self._filepathEdit.setReadOnly(False)
     self._filepathEdit.setSizePolicy(QSizePolicy.Expanding,
                                      QSizePolicy.Expanding)
     self._filepathButton.setText('...')
     self._filepathButton.setFixedSize(25, 23)
     self._filepathButton.setAutoRaise(True)
     self._filepathButton.setIcon(QIcon(ico))
     self._filepathEdit.setContextMenuPolicy(Qt.CustomContextMenu)
     
     self.setWindowTitle('Load File')
     self.setAcceptDrops(True)
     
     # define the layout
     layout = QHBoxLayout()
     layout.setContentsMargins(0, 0, 0, 0)
     layout.setSpacing(0)
     layout.addWidget(self._filepathEdit)
     layout.addWidget(self._filepathButton)
     self.setLayout(layout)
     
     # create connections
     self._filepathEdit.installEventFilter(self)
     
     self._filepathButton.clicked.connect(   self.pickFilepath )
     self._filepathEdit.textChanged.connect( self.emitFilepathChanged )
     self._filepathEdit.textChanged.connect( self.validateFilepath )
     self._filepathEdit.customContextMenuRequested.connect( self.showMenu )
Esempio n. 7
0
    def setLineEdit(self, edit):
        """
        Sets the line edit for this widget.
        
        :warning    If the inputed edit is NOT an instance of XLineEdit, \
                    this method will destroy the edit and create a new \
                    XLineEdit instance.
        
        :param      edit | <XLineEdit>
        """
        if (edit and not isinstance(edit, XLineEdit)):
            edit.setParent(None)
            edit.deleteLater()

            edit = XLineEdit(self)

        edit.installEventFilter(self)
        super(XComboBox, self).setLineEdit(edit)
Esempio n. 8
0
 def setLineEdit( self, edit ):
     """
     Sets the line edit for this widget.
     
     :warning    If the inputed edit is NOT an instance of XLineEdit, \
                 this method will destroy the edit and create a new \
                 XLineEdit instance.
     
     :param      edit | <XLineEdit>
     """
     if ( edit and not isinstance(edit, XLineEdit) ):
         edit.setParent(None)
         edit.deleteLater()
         
         edit = XLineEdit(self)
     
     edit.installEventFilter(self)
     super(XComboBox, self).setLineEdit(edit)
Esempio n. 9
0
    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)
Esempio n. 10
0
 def setEditable( self, state ):
     """
     Sets whether or not this combobox will be editable, updating its \
     line edit to an XLineEdit if necessary.
     
     :param      state | <bool>
     """
     super(XComboBox, self).setEditable(state)
     
     if ( state ):
         edit = self.lineEdit()
         if ( edit and isinstance(edit, XLineEdit) ):
             return
         elif ( edit ):
             edit.setParent(None)
             edit.deleteLater()
         
         edit = XLineEdit(self)
         edit.setHint(self.hint())
         self.setLineEdit(edit)
Esempio n. 11
0
    def setEditable(self, state):
        """
        Sets whether or not this combobox will be editable, updating its \
        line edit to an XLineEdit if necessary.
        
        :param      state | <bool>
        """
        super(XComboBox, self).setEditable(state)

        if state:
            edit = self.lineEdit()
            if edit and isinstance(edit, XLineEdit):
                return
            elif edit:
                edit.setParent(None)
                edit.deleteLater()

            edit = XLineEdit(self)
            edit.setHint(self.hint())
            self.setLineEdit(edit)
Esempio n. 12
0
    def __init__(self, parent=None):
        super(XComboBox, self).__init__(parent)

        # define custom properties
        self._checkable = False
        self._hint = ''
        self._separator = ','

        # setup the checkable popup widget
        self._checkablePopup = None

        # set default properties
        self.setLineEdit(XLineEdit(self))
Esempio n. 13
0
    def setEditable(self, state):
        """
        Sets whether or not this label should be editable or not.
        
        :param      state | <bool>
        """
        self._editable = state

        if state and not self._lineEdit:
            self.setLineEdit(XLineEdit(self))

        elif not state and self._lineEdit:
            self._lineEdit.close()
            self._lineEdit.setParent(None)
            self._lineEdit.deleteLater()
            self._lineEdit = None
    def setQuery(self, query):
        """
        Sets the query instance for this widget to the inputed query.
        
        :param      query | <orb.Query> || <orb.QueryCompound>
        """
        if hash(query) == hash(self._query):
            return

        self._query = query

        if QueryCompound.typecheck(query):
            self.uiColumnDDL.hide()
            self.uiOperatorDDL.hide()

            # setup the compound editor
            editor = XLineEdit(self)
            editor.setReadOnly(True)
            editor.setText(query.name() + ' %s' % str(query))
            editor.setHint(str(query))

            self.setEditor(editor)

        else:
            self.uiColumnDDL.show()
            self.uiOperatorDDL.show()

            text = query.columnName()
            self.uiColumnDDL.setCurrentSchemaPath(str(text))

            self.uiOperatorDDL.blockSignals(True)
            plug = self.currentPlugin()
            if plug:
                op = plug.operator(query.operatorType(), query.value())

                index = self.uiOperatorDDL.findText(op)
                if index != -1:
                    self.uiOperatorDDL.setCurrentIndex(index)

            self.uiOperatorDDL.blockSignals(False)

        self.refreshButtons()
Esempio n. 15
0
 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)
Esempio n. 16
0
 def setQuery(self, query):
     """
     Sets the query instance for this widget to the inputed query.
     
     :param      query | <orb.Query> || <orb.QueryCompound>
     """
     if not query.isNull() and hash(query) == hash(self._query):
         return
     
     self._query = query
     
     if QueryCompound.typecheck(query):
         self.uiColumnDDL.hide()
         self.uiOperatorDDL.hide()
         
         # setup the compound editor
         editor = XLineEdit(self)
         editor.setReadOnly(True)
         editor.setText(query.name() + ' %s' % nativestring(query))
         editor.setHint(nativestring(query))
         
         self.setEditor(editor)
     
     else:
         self.uiColumnDDL.show()
         self.uiOperatorDDL.show()
         
         text = query.columnName()
         self.uiColumnDDL.setCurrentSchemaPath(nativestring(text))
         
         self.uiOperatorDDL.blockSignals(True)
         plug = self.currentPlugin()
         if plug:
             op = plug.operator(query.operatorType(), query.value())
             
             index = self.uiOperatorDDL.findText(op)
             if index != -1:
                 self.uiOperatorDDL.setCurrentIndex(index)
         
         self.uiOperatorDDL.blockSignals(False)
     
     self.refreshButtons()
Esempio n. 17
0
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
Esempio n. 18
0
class XKeyValueDialog(QDialog):
    def __init__( self, parent = None ):
        super(XKeyValueDialog, self).__init__(parent)
        
        # create the interface
        self._keyEdit   = XLineEdit(self)
        self._keyEdit.setMaximumWidth(80)
        self._keyEdit.setHint( 'set key' )
        
        self._valueEdit = XLineEdit(self)
        self._valueEdit.setHint( 'set value' )
        
        hbox = QHBoxLayout()
        hbox.addWidget(self._keyEdit)
        hbox.addWidget(self._valueEdit)
        
        opts    = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        buttons = QDialogButtonBox( opts, Qt.Horizontal, self )
        
        vbox = QVBoxLayout()
        vbox.addLayout(hbox)
        vbox.addWidget(buttons)
        
        # update the look and size
        self.setLayout(vbox)
        self.setWindowTitle('Edit Pair')
        self.setMinimumWidth(350)
        self.adjustSize()
        self.setFixedHeight(self.height())
        
        # create connections
        buttons.accepted.connect( self.accept )
        buttons.rejected.connect( self.reject )
    
    def key( self ):
        """
        Returns the current value of the current pair's key.
        
        :return     <str>
        """
        return nativestring(self._keyEdit.text())
    
    def setKey( self, key ):
        """
        Sets the current value of the current pair's key.
        
        :param      key | <str>
        """
        self._keyEdit.setText(key)
    
    def setValue( self, value ):
        """
        Sets the current value of the current pair's value.
        
        :param      value | <str>
        """
        self._valueEdit.setText(value)
    
    def value( self ):
        """
        Returns the current value of the current pair's value.
        
        :return     <str>
        """
        return nativestring(self._valueEdit.text())
    
    @staticmethod
    def edit( key = '', value = '', parent = None ):
        """
        Prompts the user to edit the inputed key/value pairing.
        
        :param      key     | <str>
                    value   | <str>
                    parent  | <QWidget>
        
        :return     (<bool> accepted, <str> key, <str> value)
        """
        dlg = XKeyValueDialog(parent)
        dlg.setKey(key)
        dlg.setValue(value)
        
        if ( dlg.exec_() ):
            return (True, dlg.key(), dlg.value())
        
        return (False, '', '')
Esempio n. 19
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()
Esempio n. 20
0
class XFilepathEdit(QWidget):
    """
    The XFilepathEdit class provides a common interface to prompt the user to
    select a filepath from the filesystem.  It can be configured to load
    directories, point to a save file path location, or to an open file path
    location.  It can also be setup to color changed based on the validity
    of the existance of the filepath.
    
    == Example ==
    
    |>>> from projexui.widgets.xfilepathedit import XFilepathEdit
    |>>> import projexui
    |
    |>>> # create the edit
    |>>> edit = projexui.testWidget(XFilepathEdit)
    |
    |>>> # set the filepath
    |>>> edit.setFilepath('/path/to/file')
    |
    |>>> # prompt the user to select the filepath
    |>>> edit.pickFilepath()
    |
    |>>> # enable the coloring validation
    |>>> edit.setValidated(True)
    """

    __designer_icon__ = projexui.resources.find('img/file.png')

    Mode = enum('OpenFile', 'SaveFile', 'Path', 'OpenFiles')

    filepathChanged = qt.Signal(str)

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

        # define custom properties
        self._validated = False
        self._validForeground = QColor(0, 120, 0)
        self._validBackground = QColor(0, 120, 0, 100)
        self._invalidForeground = QColor(255, 0, 0)
        self._invalidBackground = QColor(255, 0, 0, 100)
        self._normalizePath = False

        self._filepathMode = XFilepathEdit.Mode.OpenFile
        self._filepathEdit = XLineEdit(self)
        self._filepathButton = QToolButton(self)
        self._filepathTypes = 'All Files (*.*)'

        # set default properties
        ico = projexui.resources.find('img/folder.png')
        self._filepathEdit.setReadOnly(False)
        self._filepathButton.setText('...')
        self._filepathButton.setFixedSize(25, 23)
        self._filepathButton.setAutoRaise(True)
        self._filepathButton.setIcon(QIcon(ico))
        self._filepathEdit.setContextMenuPolicy(Qt.CustomContextMenu)

        self.setWindowTitle('Load File')
        self.setAcceptDrops(True)

        # define the layout
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self._filepathEdit)
        layout.addWidget(self._filepathButton)
        self.setLayout(layout)

        # create connections
        self._filepathEdit.installEventFilter(self)

        self._filepathButton.clicked.connect(self.pickFilepath)
        self._filepathEdit.textChanged.connect(self.emitFilepathChanged)
        self._filepathEdit.textChanged.connect(self.validateFilepath)
        self._filepathEdit.customContextMenuRequested.connect(self.showMenu)

    def autoRaise(self):
        """
        Returns whether or not the tool button will auto raise.
        
        :return     <bool>
        """
        return self._filepathButton.autoRaise()

    @qt.Slot()
    def clearFilepath(self):
        """
        Clears the filepath contents for this path.
        """
        self.setFilepath('')

    @qt.Slot()
    def copyFilepath(self):
        """
        Copies the current filepath contents to the current clipboard.
        """
        clipboard = QApplication.instance().clipboard()
        clipboard.setText(self.filepath())
        clipboard.setText(self.filepath(), clipboard.Selection)

    def dragEnterEvent(self, event):
        """
        Processes drag enter events.
        
        :param      event | <QDragEvent>
        """
        if (event.mimeData().hasUrls()):
            event.acceptProposedAction()

    def dragMoveEvent(self, event):
        """
        Processes drag move events.
        
        :param      event | <QDragEvent>
        """
        if (event.mimeData().hasUrls()):
            event.acceptProposedAction()

    def dropEvent(self, event):
        """
        Processes drop event.
        
        :param      event | <QDropEvent>
        """
        if (event.mimeData().hasUrls()):
            url = event.mimeData().urls()[0]
            filepath = url.toLocalFile()
            if (filepath):
                self.setFilepath(filepath)

    def emitFilepathChanged(self):
        """
        Emits the filepathChanged signal for this widget if the signals are \
        not being blocked.
        """
        if (not self.signalsBlocked()):
            self.filepathChanged.emit(self.filepath())

    def eventFilter(self, object, event):
        """
        Overloads the eventFilter to look for click events on the line edit.
        
        :param      object | <QObject>
                    event  | <QEvent>
        """
        if ( object == self._filepathEdit and \
             self._filepathEdit.isReadOnly() and \
             event.type() == event.MouseButtonPress and \
             event.button() == Qt.LeftButton ):
            self.pickFilepath()

        return False

    def filepath(self, validated=False):
        """
        Returns the filepath for this widget.  If the validated flag is set \
        then this method will only return if the file or folder actually \
        exists for this path.  In the case of a SaveFile, only the base folder \
        needs to exist on the system, in other modes the actual filepath must \
        exist.  If not validated, the text will return whatever is currently \
        entered.
        
        :return     <str>
        """
        paths = self.filepaths()
        if not paths:
            return ''

        if not validated or self.isValid():
            return paths[0]
        return ''

    def filepaths(self):
        """
        Returns a list of the filepaths for this edit.
        
        :return     [<str>, ..]
        """
        return str(self._filepathEdit.text()).split(os.path.pathsep)

    def filepathMode(self):
        """
        Returns the filepath mode for this widget.
        
        :return     <XFilepathEdit.Mode>
        """
        return self._filepathMode

    def filepathModeText(self):
        """
        Returns the text representation for this filepath mode.
        
        :return     <str>
        """
        return XFilepathEdit.Mode[self._filepathMode]

    def filepathTypes(self):
        """
        Returns the filepath types that will be used for this widget.
        
        :return     <str>
        """
        return self._filepathTypes

    def hint(self):
        """
        Returns the hint for this filepath.
        
        :return     <str>
        """
        return self._filepathEdit.hint()

    def icon(self):
        """
        Returns the icon that is used for this filepath widget.
        
        :return     <QIcon>
        """
        return self._filepathButton.icon()

    def invalidBackground(self):
        """
        Returns the invalid background color for this widget.
        
        :return     <QColor>
        """
        return self._invalidBackground

    def invalidForeground(self):
        """
        Returns the invalid foreground color for this widget.
        
        :return     <QColor>
        """
        return self._invalidForeground

    def isValid(self):
        """
        Returns whether or not the filepath exists on the system. \
        In the case of a SaveFile, only the base folder \
        needs to exist on the system, in other modes the actual filepath must \
        exist.
        
        :return     <bool>
        """
        check = str(self._filepathEdit.text()).split(os.path.pathsep)[0]
        if (self.filepathMode() == XFilepathEdit.Mode.SaveFile):
            check = os.path.dirname(check)

        return os.path.exists(check)

    def isValidated(self):
        """
        Set whether or not to validate the filepath as the user is working \
        with it.
        
        :return     <bool>
        """
        return self._validated

    def isReadOnly(self):
        """
        Returns if the widget is read only for text editing or not.
        
        :return     <bool>
        """
        return self._filepathEdit.isReadOnly()

    def normalizePath(self):
        """
        Returns whether or not the path should be normalized for the current
        operating system.  When off, it will be defaulted to forward slashes
        (/).
        
        :return     <bool>
        """
        return self._normalizePath

    def pickFilepath(self):
        """
        Prompts the user to select a filepath from the system based on the \
        current filepath mode.
        """
        mode = self.filepathMode()

        filepath = ''
        filepaths = []
        curr_dir = str(self._filepathEdit.text())
        if (not curr_dir):
            curr_dir = QDir.currentPath()

        if mode == XFilepathEdit.Mode.SaveFile:
            filepath = QFileDialog.getSaveFileName(self, self.windowTitle(),
                                                   curr_dir,
                                                   self.filepathTypes())

        elif mode == XFilepathEdit.Mode.OpenFile:
            filepath = QFileDialog.getOpenFileName(self, self.windowTitle(),
                                                   curr_dir,
                                                   self.filepathTypes())

        elif mode == XFilepathEdit.Mode.OpenFiles:
            filepaths = QFileDialog.getOpenFileNames(self, self.windowTitle(),
                                                     curr_dir,
                                                     self.filepathTypes())

        else:
            filepath = QFileDialog.getExistingDirectory(
                self, self.windowTitle(), curr_dir)

        if filepath:
            if type(filepath) == tuple:
                filepath = filepath[0]
            self.setFilepath(str(filepath))
        elif filepaths:
            self.setFilepaths(map(str, filepaths))

    def setAutoRaise(self, state):
        """
        Sets whether or not the tool button will auto raise.
        
        :param      state | <bool>
        """
        self._filepathButton.setAutoRaise(state)

    @qt.Slot(int)
    def setFilepathMode(self, mode):
        """
        Sets the filepath mode for this widget to the inputed mode.
        
        :param      mode | <XFilepathEdit.Mode>
        """
        self._filepathMode = mode

    @qt.Slot(str)
    def setFilepathModeText(self, text):
        """
        Sets the filepath mode for this widget based on the inputed text.
        
        :param      text | <str>
        
        :return     <bool> | success
        """
        try:
            self.setFilepathMode(XFilepathEdit.Mode[str(text)])
            return True
        except KeyError:
            return False

    @qt.Slot(str)
    def setFilepathTypes(self, filepathTypes):
        """
        Sets the filepath type string that will be used when looking up \
        filepaths.
        
        :param      filepathTypes | <str>
        """
        self._filepathTypes = filepathTypes

    @qt.Slot(str)
    def setFilepath(self, filepath):
        """
        Sets the filepath text for this widget to the inputed path.
        
        :param      filepath | <str>
        """
        if self.normalizePath():
            filepath = os.path.normpath(str(filepath))
        else:
            filepath = os.path.normpath(str(filepath)).replace('\\', '/')

        self._filepathEdit.setText(filepath)

    def setFilepaths(self, filepaths):
        """
        Sets the list of the filepaths for this widget to the inputed paths.
        
        :param      filepaths | [<str>, ..]
        """
        self.setFilepath(os.path.pathsep.join(filepaths))

    def setHint(self, hint):
        """
        Sets the hint for this filepath.
        
        :param      hint | <str>
        """
        if self.normalizePath():
            filepath = os.path.normpath(str(hint))
        else:
            filepath = os.path.normpath(str(hint)).replace('\\', '/')

        self._filepathEdit.setHint(hint)

    def setIcon(self, icon):
        """
        Sets the icon that will be used for this widget's tool button.
        
        :param      icon | <QIcon> || <str>
        """
        self._filepathButton.setIcon(QIcon(icon))

    def setInvalidBackground(self, bg):
        """
        Sets the invalid background color for this widget to the inputed widget.
        
        :param      bg | <QColor>
        """
        self._invalidBackground = QColor(bg)

    def setInvalidForeground(self, fg):
        """
        Sets the invalid foreground color for this widget to the inputed widget.
        
        :param      fg | <QColor>
        """
        self._invalidForeground = QColor(fg)

    def setNormalizePath(self, state):
        """
        Sets whether or not the path should be normalized for the current
        operating system.  When off, it will be defaulted to forward slashes
        (/).
        
        :param      state | <bool>
        """
        self._normalizePath = state

    @qt.Slot(bool)
    def setReadOnly(self, state):
        """
        Sets whether or not this filepath widget is readonly in the text edit.
        
        :param      state | <bool>
        """
        self._filepathEdit.setReadOnly(state)

    @qt.Slot(bool)
    def setValidated(self, state):
        """
        Set whether or not to validate the path as the user edits it.
        
        :param      state | <bool>
        """
        self._validated = state
        palette = self.palette()

        # reset the palette to default, revalidate
        self._filepathEdit.setPalette(palette)
        self.validate()

    def setValidBackground(self, bg):
        """
        Sets the valid background color for this widget to the inputed color.
        
        :param      bg | <QColor>
        """
        self._validBackground = QColor(bg)

    def setValidForeground(self, fg):
        """
        Sets the valid foreground color for this widget to the inputed color.
        
        :param      fg | <QColor>
        """
        self._validForeground = QColor(fg)

    def showMenu(self, pos):
        """
        Popups a menu for this widget.
        """
        menu = QMenu(self)
        menu.setAttribute(Qt.WA_DeleteOnClose)
        menu.addAction('Clear').triggered.connect(self.clearFilepath)
        menu.addSeparator()
        menu.addAction('Copy Filepath').triggered.connect(self.copyFilepath)

        menu.exec_(self.mapToGlobal(pos))

    def validBackground(self):
        """
        Returns the valid background color for this widget.
        
        :return     <QColor>
        """
        return self._validBackground

    def validForeground(self):
        """
        Returns the valid foreground color for this widget.
        
        :return     <QColor>
        """
        return self._validForeground

    def validateFilepath(self):
        """
        Alters the color scheme based on the validation settings.
        """
        if (not self.isValidated()):
            return

        valid = self.isValid()
        if (not valid):
            fg = self.invalidForeground()
            bg = self.invalidBackground()
        else:
            fg = self.validForeground()
            bg = self.validBackground()

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

    # map Qt properties
    x_autoRaise = qt.Property(bool, autoRaise, setAutoRaise)
    x_filepathTypes = qt.Property(str, filepathTypes, setFilepathTypes)
    x_filepath = qt.Property(str, filepath, setFilepath)
    x_readOnly = qt.Property(bool, isReadOnly, setReadOnly)
    x_validated = qt.Property(bool, isValidated, setValidated)
    x_hint = qt.Property(str, hint, setHint)
    x_icon = qt.Property('QIcon', icon, setIcon)
    x_normalizePath = qt.Property(bool, normalizePath, setNormalizePath)

    x_invalidForeground = qt.Property('QColor', invalidForeground,
                                      setInvalidForeground)

    x_invalidBackground = qt.Property('QColor', invalidBackground,
                                      setInvalidBackground)

    x_validForeground = qt.Property('QColor', validForeground,
                                    setValidForeground)

    x_validBackground = qt.Property('QColor', validBackground,
                                    setValidBackground)

    x_filepathModeText = qt.Property(str, filepathModeText,
                                     setFilepathModeText)
Esempio n. 21
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()
Esempio n. 22
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)
Esempio n. 23
0
class XFilepathEdit(QWidget):
    """
    The XFilepathEdit class provides a common interface to prompt the user to
    select a filepath from the filesystem.  It can be configured to load
    directories, point to a save file path location, or to an open file path
    location.  It can also be setup to color changed based on the validity
    of the existance of the filepath.
    
    == Example ==
    
    |>>> from projexui.widgets.xfilepathedit import XFilepathEdit
    |>>> import projexui
    |
    |>>> # create the edit
    |>>> edit = projexui.testWidget(XFilepathEdit)
    |
    |>>> # set the filepath
    |>>> edit.setFilepath('/path/to/file')
    |
    |>>> # prompt the user to select the filepath
    |>>> edit.pickFilepath()
    |
    |>>> # enable the coloring validation
    |>>> edit.setValidated(True)
    """
    
    __designer_icon__ = projexui.resources.find('img/file.png')
    
    Mode = enum('OpenFile', 'SaveFile', 'Path', 'OpenFiles')
    
    filepathChanged = qt.Signal(str)
    
    def __init__( self, parent = None ):
        super(XFilepathEdit, self).__init__( parent )
        
        # define custom properties
        self._validated         = False
        self._validForeground   = QColor(0, 120, 0)
        self._validBackground   = QColor(0, 120, 0, 100)
        self._invalidForeground = QColor(255, 0, 0)
        self._invalidBackground = QColor(255, 0, 0, 100)
        self._normalizePath     = False
        
        self._filepathMode      = XFilepathEdit.Mode.OpenFile
        self._filepathEdit      = XLineEdit(self)
        self._filepathButton    = QToolButton(self)
        self._filepathTypes     = 'All Files (*.*)'
        
        # set default properties
        ico = projexui.resources.find('img/folder.png')
        self._filepathEdit.setReadOnly(False)
        self._filepathButton.setText('...')
        self._filepathButton.setFixedSize(25, 23)
        self._filepathButton.setAutoRaise(True)
        self._filepathButton.setIcon(QIcon(ico))
        self._filepathEdit.setContextMenuPolicy(Qt.CustomContextMenu)
        
        self.setWindowTitle('Load File')
        self.setAcceptDrops(True)
        
        # define the layout
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self._filepathEdit)
        layout.addWidget(self._filepathButton)
        self.setLayout(layout)
        
        # create connections
        self._filepathEdit.installEventFilter(self)
        
        self._filepathButton.clicked.connect(   self.pickFilepath )
        self._filepathEdit.textChanged.connect( self.emitFilepathChanged )
        self._filepathEdit.textChanged.connect( self.validateFilepath )
        self._filepathEdit.customContextMenuRequested.connect( self.showMenu )
    
    def autoRaise( self ):
        """
        Returns whether or not the tool button will auto raise.
        
        :return     <bool>
        """
        return self._filepathButton.autoRaise()
    
    @qt.Slot()
    def clearFilepath( self ):
        """
        Clears the filepath contents for this path.
        """
        self.setFilepath('')
    
    @qt.Slot()
    def copyFilepath( self ):
        """
        Copies the current filepath contents to the current clipboard.
        """
        clipboard = QApplication.instance().clipboard()
        clipboard.setText(self.filepath())
        clipboard.setText(self.filepath(), clipboard.Selection)
    
    def dragEnterEvent( self, event ):
        """
        Processes drag enter events.
        
        :param      event | <QDragEvent>
        """
        if ( event.mimeData().hasUrls() ):
            event.acceptProposedAction()
    
    def dragMoveEvent( self, event ):
        """
        Processes drag move events.
        
        :param      event | <QDragEvent>
        """
        if ( event.mimeData().hasUrls() ):
            event.acceptProposedAction()
    
    def dropEvent( self, event ):
        """
        Processes drop event.
        
        :param      event | <QDropEvent>
        """
        if ( event.mimeData().hasUrls() ):
            url      = event.mimeData().urls()[0]
            filepath = url.toLocalFile()
            if ( filepath ):
                self.setFilepath(filepath)
    
    def emitFilepathChanged( self ):
        """
        Emits the filepathChanged signal for this widget if the signals are \
        not being blocked.
        """
        if ( not self.signalsBlocked() ):
            self.filepathChanged.emit(self.filepath())
    
    def eventFilter( self, object, event ):
        """
        Overloads the eventFilter to look for click events on the line edit.
        
        :param      object | <QObject>
                    event  | <QEvent>
        """
        if ( object == self._filepathEdit and \
             self._filepathEdit.isReadOnly() and \
             event.type() == event.MouseButtonPress and \
             event.button() == Qt.LeftButton ):
            self.pickFilepath()
            
        return False
    
    def filepath( self, validated = False ):
        """
        Returns the filepath for this widget.  If the validated flag is set \
        then this method will only return if the file or folder actually \
        exists for this path.  In the case of a SaveFile, only the base folder \
        needs to exist on the system, in other modes the actual filepath must \
        exist.  If not validated, the text will return whatever is currently \
        entered.
        
        :return     <str>
        """
        paths = self.filepaths()
        if not paths:
            return ''
        
        if not validated or self.isValid():
            return paths[0]
        return ''
    
    def filepaths(self):
        """
        Returns a list of the filepaths for this edit.
        
        :return     [<str>, ..]
        """
        return str(self._filepathEdit.text()).split(os.path.pathsep)
    
    def filepathMode( self ):
        """
        Returns the filepath mode for this widget.
        
        :return     <XFilepathEdit.Mode>
        """
        return self._filepathMode
    
    def filepathModeText( self ):
        """
        Returns the text representation for this filepath mode.
        
        :return     <str>
        """
        return XFilepathEdit.Mode[self._filepathMode]
    
    def filepathTypes( self ):
        """
        Returns the filepath types that will be used for this widget.
        
        :return     <str>
        """
        return self._filepathTypes
    
    def hint( self ):
        """
        Returns the hint for this filepath.
        
        :return     <str>
        """
        return self._filepathEdit.hint()
    
    def icon( self ):
        """
        Returns the icon that is used for this filepath widget.
        
        :return     <QIcon>
        """
        return self._filepathButton.icon()
    
    def invalidBackground( self ):
        """
        Returns the invalid background color for this widget.
        
        :return     <QColor>
        """
        return self._invalidBackground
    
    def invalidForeground( self ):
        """
        Returns the invalid foreground color for this widget.
        
        :return     <QColor>
        """
        return self._invalidForeground
    
    def isValid( self ):
        """
        Returns whether or not the filepath exists on the system. \
        In the case of a SaveFile, only the base folder \
        needs to exist on the system, in other modes the actual filepath must \
        exist.
        
        :return     <bool>
        """
        check = str(self._filepathEdit.text()).split(os.path.pathsep)[0]
        if ( self.filepathMode() == XFilepathEdit.Mode.SaveFile ):
            check = os.path.dirname(check)
        
        return os.path.exists(check)
    
    def isValidated( self ):
        """
        Set whether or not to validate the filepath as the user is working \
        with it.
        
        :return     <bool>
        """
        return self._validated
    
    def isReadOnly( self ):
        """
        Returns if the widget is read only for text editing or not.
        
        :return     <bool>
        """
        return self._filepathEdit.isReadOnly()
    
    def normalizePath(self):
        """
        Returns whether or not the path should be normalized for the current
        operating system.  When off, it will be defaulted to forward slashes
        (/).
        
        :return     <bool>
        """
        return self._normalizePath
    
    def pickFilepath( self ):
        """
        Prompts the user to select a filepath from the system based on the \
        current filepath mode.
        """
        mode = self.filepathMode()
        
        filepath = ''
        filepaths = []
        curr_dir = str(self._filepathEdit.text())
        if ( not curr_dir ):
            curr_dir = QDir.currentPath()
        
        if mode == XFilepathEdit.Mode.SaveFile:
            filepath = QFileDialog.getSaveFileName( self,
                                                    self.windowTitle(),
                                                    curr_dir,
                                                    self.filepathTypes() )
                                                    
        elif mode == XFilepathEdit.Mode.OpenFile:
            filepath = QFileDialog.getOpenFileName( self,
                                                    self.windowTitle(),
                                                    curr_dir,
                                                    self.filepathTypes() )
        
        elif mode == XFilepathEdit.Mode.OpenFiles:
            filepaths = QFileDialog.getOpenFileNames( self,
                                                      self.windowTitle(),
                                                      curr_dir,
                                                      self.filepathTypes() )
        
        else:
            filepath = QFileDialog.getExistingDirectory( self,
                                                         self.windowTitle(),
                                                         curr_dir )
        
        if filepath:
            if type(filepath) == tuple:
                filepath = filepath[0]
            self.setFilepath(str(filepath))
        elif filepaths:
            self.setFilepaths(map(str, filepaths))
    
    def setAutoRaise( self, state ):
        """
        Sets whether or not the tool button will auto raise.
        
        :param      state | <bool>
        """
        self._filepathButton.setAutoRaise(state)
    
    @qt.Slot(int)
    def setFilepathMode( self, mode ):
        """
        Sets the filepath mode for this widget to the inputed mode.
        
        :param      mode | <XFilepathEdit.Mode>
        """
        self._filepathMode = mode
    
    @qt.Slot(str)
    def setFilepathModeText( self, text ):
        """
        Sets the filepath mode for this widget based on the inputed text.
        
        :param      text | <str>
        
        :return     <bool> | success
        """
        try:
            self.setFilepathMode(XFilepathEdit.Mode[str(text)])
            return True
        except KeyError:
            return False
    
    @qt.Slot(str)
    def setFilepathTypes( self, filepathTypes ):
        """
        Sets the filepath type string that will be used when looking up \
        filepaths.
        
        :param      filepathTypes | <str>
        """
        self._filepathTypes = filepathTypes
    
    @qt.Slot(str)
    def setFilepath(self, filepath):
        """
        Sets the filepath text for this widget to the inputed path.
        
        :param      filepath | <str>
        """
        if self.normalizePath():
            filepath = os.path.normpath(str(filepath))
        else:
            filepath = os.path.normpath(str(filepath)).replace('\\', '/')
            
        self._filepathEdit.setText(filepath)
    
    def setFilepaths(self, filepaths):
        """
        Sets the list of the filepaths for this widget to the inputed paths.
        
        :param      filepaths | [<str>, ..]
        """
        self.setFilepath(os.path.pathsep.join(filepaths))
    
    def setHint(self, hint):
        """
        Sets the hint for this filepath.
        
        :param      hint | <str>
        """
        if self.normalizePath():
            filepath = os.path.normpath(str(hint))
        else:
            filepath = os.path.normpath(str(hint)).replace('\\', '/')
            
        self._filepathEdit.setHint(hint)
    
    def setIcon( self, icon ):
        """
        Sets the icon that will be used for this widget's tool button.
        
        :param      icon | <QIcon> || <str>
        """
        self._filepathButton.setIcon(QIcon(icon))
    
    def setInvalidBackground( self, bg ):
        """
        Sets the invalid background color for this widget to the inputed widget.
        
        :param      bg | <QColor>
        """
        self._invalidBackground = QColor(bg)
    
    def setInvalidForeground( self, fg ):
        """
        Sets the invalid foreground color for this widget to the inputed widget.
        
        :param      fg | <QColor>
        """
        self._invalidForeground = QColor(fg)
    
    def setNormalizePath(self, state):
        """
        Sets whether or not the path should be normalized for the current
        operating system.  When off, it will be defaulted to forward slashes
        (/).
        
        :param      state | <bool>
        """
        self._normalizePath = state
    
    @qt.Slot(bool)
    def setReadOnly( self, state ):
        """
        Sets whether or not this filepath widget is readonly in the text edit.
        
        :param      state | <bool>
        """
        self._filepathEdit.setReadOnly(state)
    
    @qt.Slot(bool)
    def setValidated( self, state ):
        """
        Set whether or not to validate the path as the user edits it.
        
        :param      state | <bool>
        """
        self._validated = state
        palette = self.palette()
        
        # reset the palette to default, revalidate
        self._filepathEdit.setPalette(palette)
        self.validate()
    
    def setValidBackground( self, bg ):
        """
        Sets the valid background color for this widget to the inputed color.
        
        :param      bg | <QColor>
        """
        self._validBackground = QColor(bg)
    
    def setValidForeground( self, fg ):
        """
        Sets the valid foreground color for this widget to the inputed color.
        
        :param      fg | <QColor>
        """
        self._validForeground = QColor(fg)
    
    def showMenu( self, pos ):
        """
        Popups a menu for this widget.
        """
        menu = QMenu(self)
        menu.setAttribute(Qt.WA_DeleteOnClose)
        menu.addAction('Clear').triggered.connect(self.clearFilepath)
        menu.addSeparator()
        menu.addAction('Copy Filepath').triggered.connect(self.copyFilepath)
        
        menu.exec_(self.mapToGlobal(pos))
    
    def validBackground( self ):
        """
        Returns the valid background color for this widget.
        
        :return     <QColor>
        """
        return self._validBackground
    
    def validForeground( self ):
        """
        Returns the valid foreground color for this widget.
        
        :return     <QColor>
        """
        return self._validForeground
    
    def validateFilepath( self ):
        """
        Alters the color scheme based on the validation settings.
        """
        if ( not self.isValidated() ):
            return
        
        valid = self.isValid()
        if ( not valid ):
            fg = self.invalidForeground()
            bg = self.invalidBackground()
        else:
            fg = self.validForeground()
            bg = self.validBackground()
        
        palette = self.palette()
        palette.setColor(palette.Base, bg)
        palette.setColor(palette.Text, fg)
        self._filepathEdit.setPalette(palette)
    
    # map Qt properties
    x_autoRaise         = qt.Property(bool, autoRaise,     setAutoRaise)
    x_filepathTypes     = qt.Property(str,  filepathTypes, setFilepathTypes)
    x_filepath          = qt.Property(str,  filepath,      setFilepath)
    x_readOnly          = qt.Property(bool, isReadOnly,    setReadOnly)
    x_validated         = qt.Property(bool, isValidated,   setValidated)
    x_hint              = qt.Property(str,  hint,          setHint)
    x_icon              = qt.Property('QIcon', icon,       setIcon)
    x_normalizePath     = qt.Property(bool, normalizePath, setNormalizePath)
    
    x_invalidForeground = qt.Property('QColor',
                                        invalidForeground,
                                        setInvalidForeground)
    
    x_invalidBackground = qt.Property('QColor',
                                        invalidBackground,
                                        setInvalidBackground)
    
    x_validForeground   = qt.Property('QColor',
                                        validForeground,
                                        setValidForeground)
    
    x_validBackground   = qt.Property('QColor',
                                        validBackground,
                                        setValidBackground)
    
    x_filepathModeText  = qt.Property(str, 
                                       filepathModeText, 
                                       setFilepathModeText)
Esempio n. 24
0
class XLocationWidget(QWidget):
    locationChanged = Signal(str)
    locationEdited  = Signal()
    
    def __init__( self, parent ):
        super(XLocationWidget, self).__init__(parent)
        
        # define the interface
        self._locationEdit      = XLineEdit(self)
        self._locationButton    = QToolButton(self)
        self._urlTemplate       = 'http://maps.google.com/maps?%(params)s'
        self._urlQueryKey       = 'q'
        
        self._locationButton.setAutoRaise(True)
        self._locationButton.setIcon(QIcon(resources.find('img/map.png')))
        
        self._locationEdit.setHint('no location set')
        
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self._locationEdit)
        layout.addWidget(self._locationButton)
        
        self.setLayout(layout)
        
        # create connections
        self._locationEdit.textChanged.connect(self.locationChanged)
        self._locationEdit.textEdited.connect(self.locationEdited)
        self._locationButton.clicked.connect(self.browseMaps)
    
    def blockSignals( self, state ):
        """
        Blocks the signals for this widget and its sub-parts.
        
        :param      state | <bool>
        """
        super(XLocationWidget, self).blockSignals(state)
        self._locationEdit.blockSignals(state)
        self._locationButton.blockSignals(state)
    
    def browseMaps( self ):
        """
        Brings up a web browser with the address in a Google map.
        """
        url    = self.urlTemplate()
        params = urllib.urlencode({self.urlQueryKey(): self.location()})
        
        url    = url % {'params': params}
        webbrowser.open(url)
    
    def hint( self ):
        """
        Returns the hint associated with this widget.
        
        :return     <str>
        """
        return self._locationEdit.hint()
    
    def lineEdit( self ):
        """
        Returns the line edit linked with this widget.
        
        :return     <XLineEdit>
        """
        return self._locationEdit
    
    def location( self ):
        """
        Returns the current location from the edit.
        
        :return     <str>
        """
        return nativestring(self._locationEdit.text())
    
    @Slot(str)
    def setHint( self, hint ):
        """
        Sets the hint associated with this widget.
        
        :param      hint | <str>
        """
        self._locationEdit.setHint(hint)
    
    @Slot(str)
    def setLocation( self, location ):
        """
        Sets the location for this widget to the inputed location.
        
        :param      location | <str>
        """
        self._locationEdit.setText(nativestring(location))
    
    def setUrlQueryKey( self, key ):
        """
        Sets the key for the URL to the inputed key.
        
        :param      key | <str>
        """
        self._urlQueryKey = nativestring(key)
    
    def setUrlTemplate( self, templ ):
        """
        Sets the URL path template that will be used when looking up locations
        on the web.
        
        :param      templ | <str>
        """
        self._urlQueryTemplate = nativestring(templ)
    
    def urlQueryKey( self ):
        """
        Returns the query key that will be used for this location.
        
        :return     <str>
        """
        return self._urlQueryKey
    
    def urlTemplate( self ):
        """
        Returns the url template that will be used when mapping this location.
        
        :return     <str>
        """
        return self._urlTemplate
    
    x_hint        = Property(str, hint, setHint)
    x_location    = Property(str, location, setLocation)
    x_urlQueryKey = Property(str, urlQueryKey, setUrlQueryKey)
    x_urlTemplate = Property(str, urlTemplate, setUrlTemplate)
Esempio n. 25
0
    def __init__(self, scaffold, parent=None):
        super(XScaffoldPropertiesPage, self).__init__(parent)

        # setup the scaffolding options
        self._scaffold = scaffold

        self.setTitle('Properties')
        self.setSubTitle('Setup scaffold properties')

        if scaffold.uifile():
            projexui.loadUi(__file__, self, scaffold.uifile())
        else:
            layout = QtGui.QFormLayout()

            for prop in scaffold.properties():
                # define the text
                text = prop.label
                if prop.required:
                    text += '*'
                text += ':'

                # create a checkbox
                if prop.type == 'bool':
                    widget = QtGui.QCheckBox(self)
                    widget.setProperty('propertyName', wrapVariant(prop.name))
                    widget.setText(text.strip(':'))
                    layout.addRow(None, widget)

                # create a float
                elif prop.type == 'int':
                    lbl = QtGui.QLabel(text, self)
                    widget = QtGui.QSpinBox(self)
                    widget.setProperty('propertyName', wrapVariant(prop.name))
                    layout.addRow(lbl, widget)

                # create a double
                elif prop.type == 'float':
                    lbl = QtGui.QLabel(text, self)
                    widget = QtGui.QDoubleSpinBox(self)
                    widget.setProperty('propertyName', wrapVariant(prop.name))
                    layout.addRow(lbl, widget)

                # create a text edit
                elif prop.type == 'text':
                    lbl = QtGui.QLabel(text, self)
                    widget = XTextEdit(self)
                    widget.setProperty('propertyName', wrapVariant(prop.name))
                    layout.addRow(lbl, widget)

                # create a filepath
                elif prop.type == 'file':
                    lbl = QtGui.QLabel(text, self)
                    widget = XFilepathEdit(self)

                # create an icon
                elif prop.type == 'icon':
                    widget = XIconButton(self)
                    layout.addRow(lbl, widget)

                # create a line edit
                else:
                    lbl = QtGui.QLabel(text, self)

                    if prop.choices:
                        widget = XComboBox(self)
                        widget.setProperty('dataType', 'string')
                        widget.addItems([''] + prop.choices)
                    else:
                        widget = XLineEdit(self)

                        if prop.regex:
                            regexp = QtCore.QRegExp(prop.regex)
                            validator = QtGui.QRegExpValidator(regexp, widget)
                            widget.setValidator(validator)

                    widget.setProperty('propertyName', wrapVariant(prop.name))
                    layout.addRow(lbl, widget)

            self.setLayout(layout)

        for prop, widget in self.propertyWidgetMap().items():
            if prop.default is not None:
                try:
                    widget.setHint(prop.default)
                except AttributeError:
                    projexui.setWidgetValue(widget, prop.default)
Esempio n. 26
0
 def setSectionCount(self, count):
     """
     Sets the number of editors that the serial widget should have.
     
     :param      count | <int>
     """
     # cap the sections at 10
     count = max(1, min(count, 10))
     
     # create additional editors
     while self.layout().count() < count:
         editor = XLineEdit(self)
         editor.setFont(self.font())
         editor.setReadOnly(self.isReadOnly())
         editor.setHint(self.hint())
         editor.setAlignment(QtCore.Qt.AlignCenter)
         editor.installEventFilter(self)
         editor.setSizePolicy(QtGui.QSizePolicy.Expanding,
                              QtGui.QSizePolicy.Expanding)
         editor.setMaxLength(self.sectionLength())
         editor.returnPressed.connect(self.returnPressed)
         self.layout().addWidget(editor)
     
     # remove unnecessary editors
     while count < self.layout().count():
         widget = self.layout().itemAt(0).widget()
         widget.close()
         widget.setParent(None)
         widget.deleteLater()
Esempio n. 27
0
    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)
Esempio n. 28
0
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
Esempio n. 29
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)
Esempio n. 30
0
 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 )
Esempio n. 31
0
    def setSectionCount(self, count):
        """
        Sets the number of editors that the serial widget should have.
        
        :param      count | <int>
        """
        # cap the sections at 10
        count = max(1, min(count, 10))

        # create additional editors
        while self.layout().count() < count:
            editor = XLineEdit(self)
            editor.setFont(self.font())
            editor.setReadOnly(self.isReadOnly())
            editor.setHint(self.hint())
            editor.setAlignment(QtCore.Qt.AlignCenter)
            editor.installEventFilter(self)
            editor.setSizePolicy(QtGui.QSizePolicy.Expanding,
                                 QtGui.QSizePolicy.Expanding)
            editor.setMaxLength(self.sectionLength())
            editor.returnPressed.connect(self.returnPressed)
            self.layout().addWidget(editor)

        # remove unnecessary editors
        while count < self.layout().count():
            widget = self.layout().itemAt(0).widget()
            widget.close()
            widget.setParent(None)
            widget.deleteLater()
Esempio n. 32
0
class XLocationWidget(QWidget):
    locationChanged = qt.Signal(str)
    locationEdited = qt.Signal()

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

        # define the interface
        self._locationEdit = XLineEdit(self)
        self._locationButton = QToolButton(self)
        self._urlTemplate = 'http://maps.google.com/maps?%(params)s'
        self._urlQueryKey = 'q'

        self._locationButton.setAutoRaise(True)
        self._locationButton.setIcon(QIcon(resources.find('img/map.png')))

        self._locationEdit.setHint('no location set')

        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self._locationEdit)
        layout.addWidget(self._locationButton)

        self.setLayout(layout)

        # create connections
        self._locationEdit.textChanged.connect(self.locationChanged)
        self._locationEdit.textEdited.connect(self.locationEdited)
        self._locationButton.clicked.connect(self.browseMaps)

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

    def browseMaps(self):
        """
        Brings up a web browser with the address in a Google map.
        """
        url = self.urlTemplate()
        params = urllib.urlencode({self.urlQueryKey(): self.location()})

        url = url % {'params': params}
        webbrowser.open(url)

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

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

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

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

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

    def setUrlQueryKey(self, key):
        """
        Sets the key for the URL to the inputed key.
        
        :param      key | <str>
        """
        self._urlQueryKey = str(key)

    def setUrlTemplate(self, templ):
        """
        Sets the URL path template that will be used when looking up locations
        on the web.
        
        :param      templ | <str>
        """
        self._urlQueryTemplate = str(templ)

    def urlQueryKey(self):
        """
        Returns the query key that will be used for this location.
        
        :return     <str>
        """
        return self._urlQueryKey

    def urlTemplate(self):
        """
        Returns the url template that will be used when mapping this location.
        
        :return     <str>
        """
        return self._urlTemplate

    x_hint = qt.Property(str, hint, setHint)
    x_location = qt.Property(str, location, setLocation)
    x_urlQueryKey = qt.Property(str, urlQueryKey, setUrlQueryKey)
    x_urlTemplate = qt.Property(str, urlTemplate, setUrlTemplate)