Esempio n. 1
0
class XUrlWidget(QWidget):
    urlChanged = qt.Signal(str)
    urlEdited = qt.Signal()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    x_hint = qt.Property(str, hint, setHint)
    x_url = qt.Property(str, url, setUrl)
Esempio n. 2
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)
Esempio n. 3
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. 4
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. 5
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. 6
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)