Example #1
0
class XBasicCardWidget(XAbstractCardWidget):
    def __init__( self, parent ):
        super(XBasicCardWidget, self).__init__(parent)
        
        # define the interface
        self._thumbnailButton = XIconButton(self)
        self._thumbnailButton.setIconSize(QSize(64, 64))
        
        self._titleLabel      = QLabel(self)
        
        layout = QHBoxLayout()
        layout.addWidget(self._thumbnailButton)
        layout.addWidget(self._titleLabel)
        self.setLayout(layout)
    
    def setRecord( self, record ):
        """
        Sets the record that is linked with this widget.
        
        :param      record | <orb.Table>
        """
        super(XBasicCardWidget, self).setRecord(record)
        
        browser = self.browserWidget()
        if ( not browser ):
            return
        
        factory = browser.factory()
        if ( not factory ):
            return
        
        self._thumbnailButton.setIcon(factory.thumbnail(record))
        self._titleLabel.setText(factory.thumbnailText(record))
 def __init__( self, parent, plugin ):
     super(PluginWidget, self).__init__(parent)
     
     self._icon = QLabel(self)
     pixmap = QPixmap(plugin.iconFile())
     if pixmap.isNull():
         pixmap = QPixmap(projexui.resources.find('img/plugin_48.png'))
     self._icon.setPixmap(pixmap)
     self._icon.setMinimumWidth(48)
     self._icon.setMinimumHeight(48)
     self._icon.setAlignment(Qt.AlignCenter)
     
     self._title = QLabel(plugin.title(), self)
     self._title.setAlignment(Qt.AlignCenter)
     
     font = self.font()
     font.setPointSize(7)
     
     self._title.setFont(font)
     
     vbox = QVBoxLayout()
     vbox.addStretch()
     vbox.addWidget(self._icon)
     vbox.addWidget(self._title)
     vbox.addStretch()
     
     self.setLayout(vbox)
     
     self._plugin = plugin
Example #3
0
    def __init__(self, orientation, parent):
        super(XSplitterHandle, self).__init__(orientation, parent)

        # create a layout for the different buttons
        self._collapsed = False
        self._storedSizes = None

        self._collapseBefore = QToolButton(self)
        self._resizeGrip = QLabel(self)
        self._collapseAfter = QToolButton(self)

        self._collapseBefore.setAutoRaise(True)
        self._collapseAfter.setAutoRaise(True)

        self._collapseBefore.setCursor(Qt.ArrowCursor)
        self._collapseAfter.setCursor(Qt.ArrowCursor)

        # define the layout
        layout = QBoxLayout(QBoxLayout.LeftToRight, self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addStretch(1)
        layout.addWidget(self._collapseBefore)
        layout.addWidget(self._resizeGrip)
        layout.addWidget(self._collapseAfter)
        layout.addStretch(1)
        self.setLayout(layout)

        # set the orientation to start with
        self.setOrientation(orientation)

        # create connections
        self._collapseAfter.clicked.connect(self.toggleCollapseAfter)
        self._collapseBefore.clicked.connect(self.toggleCollapseBefore)
Example #4
0
class XBasicCardWidget(XAbstractCardWidget):
    def __init__(self, parent):
        super(XBasicCardWidget, self).__init__(parent)

        # define the interface
        self._thumbnailButton = XIconButton(self)
        self._thumbnailButton.setIconSize(QSize(64, 64))

        self._titleLabel = QLabel(self)

        layout = QHBoxLayout()
        layout.addWidget(self._thumbnailButton)
        layout.addWidget(self._titleLabel)
        self.setLayout(layout)

    def setRecord(self, record):
        """
        Sets the record that is linked with this widget.
        
        :param      record | <orb.Table>
        """
        super(XBasicCardWidget, self).setRecord(record)

        browser = self.browserWidget()
        if (not browser):
            return

        factory = browser.factory()
        if (not factory):
            return

        self._thumbnailButton.setIcon(factory.thumbnail(record))
        self._titleLabel.setText(factory.thumbnailText(record))
Example #5
0
 def getText(cls,
             parent=None,
             windowTitle='Get Text',
             label='',
             text='',
             plain=True,
             wrapped=True):
     """
     Prompts the user for a text entry using the text edit class.
     
     :param      parent | <QWidget>
                 windowTitle | <str>
                 label       | <str>
                 text        | <str>
                 plain       | <bool> | return plain text or not
     
     :return     (<str> text, <bool> accepted)
     """
     # create the dialog
     dlg = QDialog(parent)
     dlg.setWindowTitle(windowTitle)
     
     # create the layout
     layout = QVBoxLayout()
     
     # create the label
     if label:
         lbl = QLabel(dlg)
         lbl.setText(label)
         layout.addWidget(lbl)
     
     # create the widget
     widget = cls(dlg)
     widget.setText(text)
     
     if not wrapped:
         widget.setLineWrapMode(XTextEdit.NoWrap)
     
     layout.addWidget(widget)
     
     # create the buttons
     btns = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
                             Qt.Horizontal,
                             dlg)
     layout.addWidget(btns)
     
     dlg.setLayout(layout)
     dlg.adjustSize()
     
     # create connections
     btns.accepted.connect(dlg.accept)
     btns.rejected.connect(dlg.reject)
     
     if dlg.exec_():
         if plain:
             return (widget.toPlainText(), True)
         else:
             return (widget.toHtml(), True)
     else:
         return ('', False)
Example #6
0
    def getText(cls,
                parent=None,
                windowTitle='Get Text',
                label='',
                text='',
                plain=True,
                wrapped=True):
        """
        Prompts the user for a text entry using the text edit class.
        
        :param      parent | <QWidget>
                    windowTitle | <str>
                    label       | <str>
                    text        | <str>
                    plain       | <bool> | return plain text or not
        
        :return     (<str> text, <bool> accepted)
        """
        # create the dialog
        dlg = QDialog(parent)
        dlg.setWindowTitle(windowTitle)

        # create the layout
        layout = QVBoxLayout()

        # create the label
        if label:
            lbl = QLabel(dlg)
            lbl.setText(label)
            layout.addWidget(lbl)

        # create the widget
        widget = cls(dlg)
        widget.setText(text)

        if not wrapped:
            widget.setLineWrapMode(XTextEdit.NoWrap)

        layout.addWidget(widget)

        # create the buttons
        btns = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
                                Qt.Horizontal, dlg)
        layout.addWidget(btns)

        dlg.setLayout(layout)
        dlg.adjustSize()

        # create connections
        btns.accepted.connect(dlg.accept)
        btns.rejected.connect(dlg.reject)

        if dlg.exec_():
            if plain:
                return (widget.toPlainText(), True)
            else:
                return (widget.toHtml(), True)
        else:
            return ('', False)
Example #7
0
    def __init__(self, parent=None):
        super(XPagesWidget, self).__init__(parent)

        # define custom properties
        self._currentPage = 1
        self._pageCount = 10
        self._itemCount = 0
        self._pageSize = 50
        self._itemsTitle = 'items'

        self._pagesSpinner = QSpinBox()
        self._pagesSpinner.setMinimum(1)
        self._pagesSpinner.setMaximum(10)

        self._pageSizeCombo = XComboBox(self)
        self._pageSizeCombo.setHint('all')
        self._pageSizeCombo.addItems(['', '25', '50', '75', '100'])
        self._pageSizeCombo.setCurrentIndex(2)

        self._nextButton = QToolButton(self)
        self._nextButton.setAutoRaise(True)
        self._nextButton.setArrowType(Qt.RightArrow)
        self._nextButton.setFixedWidth(16)

        self._prevButton = QToolButton(self)
        self._prevButton.setAutoRaise(True)
        self._prevButton.setArrowType(Qt.LeftArrow)
        self._prevButton.setFixedWidth(16)
        self._prevButton.setEnabled(False)

        self._pagesLabel = QLabel('of 10 for ', self)
        self._itemsLabel = QLabel(' items per page', self)

        # define the interface
        layout = QHBoxLayout()
        layout.addWidget(QLabel('Page', self))
        layout.addWidget(self._prevButton)
        layout.addWidget(self._pagesSpinner)
        layout.addWidget(self._nextButton)
        layout.addWidget(self._pagesLabel)
        layout.addWidget(self._pageSizeCombo)
        layout.addWidget(self._itemsLabel)
        layout.addStretch(1)

        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        self.setLayout(layout)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

        # create connections
        self._pageSizeCombo.currentIndexChanged.connect(self.pageSizePicked)
        self._nextButton.clicked.connect(self.gotoNext)
        self._prevButton.clicked.connect(self.gotoPrevious)
        self._pagesSpinner.editingFinished.connect(self.assignCurrentPage)
Example #8
0
 def __init__( self, parent = None ):
     super(XPagesWidget, self).__init__( parent )
     
     # define custom properties
     self._currentPage       = 1
     self._pageCount         = 10
     self._itemCount         = 0
     self._pageSize          = 50
     self._itemsTitle        = 'items'
     
     self._pagesSpinner  = QSpinBox()
     self._pagesSpinner.setMinimum(1)
     self._pagesSpinner.setMaximum(10)
     
     self._pageSizeCombo = XComboBox(self)
     self._pageSizeCombo.setHint('all')
     self._pageSizeCombo.addItems(['', '25', '50', '75', '100'])
     self._pageSizeCombo.setCurrentIndex(2)
     
     self._nextButton    = QToolButton(self)
     self._nextButton.setAutoRaise(True)
     self._nextButton.setArrowType(Qt.RightArrow)
     self._nextButton.setFixedWidth(16)
     
     self._prevButton    = QToolButton(self)
     self._prevButton.setAutoRaise(True)
     self._prevButton.setArrowType(Qt.LeftArrow)
     self._prevButton.setFixedWidth(16)
     self._prevButton.setEnabled(False)
     
     self._pagesLabel = QLabel('of 10 for ', self)
     self._itemsLabel = QLabel(' items per page', self)
     
     # define the interface
     layout = QHBoxLayout()
     layout.addWidget(QLabel('Page', self))
     layout.addWidget(self._prevButton)
     layout.addWidget(self._pagesSpinner)
     layout.addWidget(self._nextButton)
     layout.addWidget(self._pagesLabel)
     layout.addWidget(self._pageSizeCombo)
     layout.addWidget(self._itemsLabel)
     layout.addStretch(1)
     
     layout.setContentsMargins(0, 0, 0, 0)
     layout.setSpacing(0)
     
     self.setLayout(layout)
     self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
     
     # create connections
     self._pageSizeCombo.currentIndexChanged.connect(self.pageSizePicked)
     self._nextButton.clicked.connect(self.gotoNext)
     self._prevButton.clicked.connect(self.gotoPrevious)
     self._pagesSpinner.editingFinished.connect(self.assignCurrentPage)
Example #9
0
 def richTextLabel(self):
     """
     Returns the label that is used for drawing the rich text to this button.
     
     :return     <QLabel>
     """
     if not self._richTextLabel:
         self._richTextLabel = QLabel(self)
         self._richTextLabel.installEventFilter(self)
         self._richTextLabel.setMargin(10)
     return self._richTextLabel
Example #10
0
    def __init__(self, parent):
        super(XBasicCardWidget, self).__init__(parent)

        # define the interface
        self._thumbnailButton = XIconButton(self)
        self._thumbnailButton.setIconSize(QSize(64, 64))

        self._titleLabel = QLabel(self)

        layout = QHBoxLayout()
        layout.addWidget(self._thumbnailButton)
        layout.addWidget(self._titleLabel)
        self.setLayout(layout)
Example #11
0
 def __init__( self, orientation, parent ):
     super(XSplitterHandle, self).__init__( orientation, parent )
     
     # create a layout for the different buttons
     self._collapsed      = False
     self._storedSizes    = None
     
     self._collapseBefore = QToolButton(self)
     self._resizeGrip     = QLabel(self)
     self._collapseAfter  = QToolButton(self)
     
     self._collapseBefore.setAutoRaise(True)
     self._collapseAfter.setAutoRaise(True)
     
     self._collapseBefore.setCursor(Qt.ArrowCursor)
     self._collapseAfter.setCursor(Qt.ArrowCursor)
     
     # define the layout
     layout = QBoxLayout(QBoxLayout.LeftToRight, self)
     layout.setContentsMargins(0, 0, 0, 0)
     layout.addStretch(1)
     layout.addWidget(self._collapseBefore)
     layout.addWidget(self._resizeGrip)
     layout.addWidget(self._collapseAfter)
     layout.addStretch(1)
     self.setLayout(layout)
     
     # set the orientation to start with
     self.setOrientation(orientation)
     
     # create connections
     self._collapseAfter.clicked.connect(  self.toggleCollapseAfter )
     self._collapseBefore.clicked.connect( self.toggleCollapseBefore )
Example #12
0
 def __init__( self, parent ):
     super(XBasicCardWidget, self).__init__(parent)
     
     # define the interface
     self._thumbnailButton = XIconButton(self)
     self._thumbnailButton.setIconSize(QSize(64, 64))
     
     self._titleLabel      = QLabel(self)
     
     layout = QHBoxLayout()
     layout.addWidget(self._thumbnailButton)
     layout.addWidget(self._titleLabel)
     self.setLayout(layout)
Example #13
0
 def getPlainText( parent, title, caption, text = '' ):
     """
     Prompts the user for more advanced text input.
     
     :param      parent  | <QWidget> || None
                 title   | <str>
                 caption | <str>
                 text    | <str>
     
     :return     (<str>, <bool> accepted)
     """
     dlg = QDialog(parent)
     dlg.setWindowTitle(title)
     
     label = QLabel(dlg)
     label.setText(caption)
     
     edit = QTextEdit(dlg)
     edit.setText(text)
     edit.selectAll()
     
     opts = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
     btns = QDialogButtonBox(opts, Qt.Horizontal, dlg)
     
     btns.accepted.connect(dlg.accept)
     btns.rejected.connect(dlg.reject)
     
     layout = QVBoxLayout()
     layout.addWidget(label)
     layout.addWidget(edit)
     layout.addWidget(btns)
     
     dlg.setLayout(layout)
     dlg.adjustSize()
     
     if ( dlg.exec_() ):
         return (edit.toPlainText(), True)
     return ('', False)
Example #14
0
    def __init__(self, parent, uifile=''):
        uifile = ''

        super(XSchemeConfigWidget, self).__init__(parent, uifile)

        # define the font widgets
        self._applicationFont = QFontComboBox(self)
        self._applicationFont.setProperty('dataName', wrapVariant('font'))
        self._applicationFont.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Preferred)

        self._applicationFontSize = QSpinBox(self)
        self._applicationFontSize.setProperty('dataName',
                                              wrapVariant('fontSize'))

        self._colorButton = XColorButton(self)

        hbox = QHBoxLayout()
        hbox.addWidget(QLabel('Font:', self))
        hbox.addWidget(self._applicationFont)
        hbox.addWidget(QLabel('Size:', self))
        hbox.addWidget(self._applicationFontSize)
        hbox.addWidget(QLabel('Quick Color:', self))
        hbox.addWidget(self._colorButton)

        # define the color tree
        self._colorTree = XColorTreeWidget(self)
        self._colorTree.setProperty('dataName', wrapVariant('colorSet'))

        vbox = QVBoxLayout()
        vbox.addLayout(hbox)
        vbox.addWidget(self._colorTree)

        self.setLayout(vbox)

        # create connections
        self._colorButton.colorChanged.connect(self._colorTree.setQuickColor)
Example #15
0
class XPagesWidget(QWidget):
    """ """
    currentPageChanged = Signal(int)
    pageSizeChanged    = Signal(int)
    pageCountChanged   = Signal(int)
    
    def __init__( self, parent = None ):
        super(XPagesWidget, self).__init__( parent )
        
        # define custom properties
        self._currentPage       = 1
        self._pageCount         = 10
        self._itemCount         = 0
        self._pageSize          = 50
        self._itemsTitle        = 'items'
        
        self._pagesSpinner  = QSpinBox()
        self._pagesSpinner.setMinimum(1)
        self._pagesSpinner.setMaximum(10)
        
        self._pageSizeCombo = XComboBox(self)
        self._pageSizeCombo.setHint('all')
        self._pageSizeCombo.addItems(['', '25', '50', '75', '100'])
        self._pageSizeCombo.setCurrentIndex(2)
        
        self._nextButton    = QToolButton(self)
        self._nextButton.setAutoRaise(True)
        self._nextButton.setArrowType(Qt.RightArrow)
        self._nextButton.setFixedWidth(16)
        
        self._prevButton    = QToolButton(self)
        self._prevButton.setAutoRaise(True)
        self._prevButton.setArrowType(Qt.LeftArrow)
        self._prevButton.setFixedWidth(16)
        self._prevButton.setEnabled(False)
        
        self._pagesLabel = QLabel('of 10 for ', self)
        self._itemsLabel = QLabel(' items per page', self)
        
        # define the interface
        layout = QHBoxLayout()
        layout.addWidget(QLabel('Page', self))
        layout.addWidget(self._prevButton)
        layout.addWidget(self._pagesSpinner)
        layout.addWidget(self._nextButton)
        layout.addWidget(self._pagesLabel)
        layout.addWidget(self._pageSizeCombo)
        layout.addWidget(self._itemsLabel)
        layout.addStretch(1)
        
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        
        self.setLayout(layout)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        
        # create connections
        self._pageSizeCombo.currentIndexChanged.connect(self.pageSizePicked)
        self._nextButton.clicked.connect(self.gotoNext)
        self._prevButton.clicked.connect(self.gotoPrevious)
        self._pagesSpinner.editingFinished.connect(self.assignCurrentPage)
    
    def assignCurrentPage( self ):
        """
        Assigns the page for the spinner to be current.
        """
        self.setCurrentPage(self._pagesSpinner.value())
    
    def currentPage( self ):
        """
        Reutrns the current page for this widget.
        
        :return     <int>
        """
        return self._currentPage
    
    @Slot()
    def gotoFirst( self ):
        """
        Goes to the first page.
        
        :sa     setCurrentPage
        """
        self.setCurrentPage(1)
    
    @Slot()
    def gotoLast( self ):
        """
        Goes to the last page.
        
        :sa     setCurrentPage
        """
        self.setCurrentPage(self.pageCount())
    
    @Slot()
    def gotoNext( self ):
        """
        Goes to the next page.
        
        :sa     setCurrentPage
        """
        next_page = self.currentPage() + 1
        if ( next_page > self.pageCount() ):
            return
        
        self.setCurrentPage(next_page)
    
    @Slot()
    def gotoPrevious( self ):
        """
        Goes to the previous page.
        
        :sa     setCurrentPage
        """
        prev_page = self.currentPage() - 1
        if ( prev_page == 0 ):
            return
        
        self.setCurrentPage(prev_page)
    
    def itemCount( self ):
        """
        Returns the total number of items this widget holds.  If no item count
        is defined, it will not be displayed in the label, otherwise it will
        show.
        
        :return     <int>
        """
        return self._itemCount
    
    def itemsTitle( self ):
        """
        Returns the items title for this instance.
        
        :return     <str>
        """
        return self._itemsTitle
    
    def pageCount( self ):
        """
        Returns the number of pages that this widget holds.
        
        :return     <int>
        """
        return self._pageCount
    
    def pageSize( self ):
        """
        Returns the number of items that should be visible in a page.
        
        :return     <int>
        """
        return self._pageSize
    
    def pageSizeOptions( self ):
        """
        Returns the list of options that will be displayed for this default
        size options.
        
        :return     [<str>, ..]
        """
        return map(str, self._pageSizeCombo.items())
    
    def pageSizePicked( self, pageSize ):
        """
        Updates when the user picks a page size.
        
        :param      pageSize | <str>
        """
        try:
            pageSize = int(self._pageSizeCombo.currentText())
        except ValueError:
            pageSize = 0
        
        self.setPageSize(pageSize)
        self.pageSizeChanged.emit(pageSize)
    
    def refreshLabels( self ):
        """
        Refreshes the labels to display the proper title and count information.
        """
        itemCount = self.itemCount()
        title = self.itemsTitle()
        
        if ( not itemCount ):
            self._itemsLabel.setText(' %s per page' % title)
        else:
            msg = ' %s per page, %i %s total' % (title, itemCount, title)
            self._itemsLabel.setText(msg)
    
    @Slot(int)
    def setCurrentPage( self, pageno ):
        """
        Sets the current page for this widget to the inputed page.
        
        :param      pageno | <int>
        """
        if ( pageno == self._currentPage ):
            return
        
        if ( pageno <= 0 ):
            pageno = 1
        
        self._currentPage = pageno
        
        self._prevButton.setEnabled(pageno > 1)
        self._nextButton.setEnabled(pageno < self.pageCount())
        
        self._pagesSpinner.blockSignals(True)
        self._pagesSpinner.setValue(pageno)
        self._pagesSpinner.blockSignals(False)
        
        if ( not self.signalsBlocked() ):
            self.currentPageChanged.emit(pageno)
    
    @Slot(int)
    def setItemCount( self, itemCount ):
        """
        Sets the item count for this page to the inputed value.
        
        :param      itemCount | <int>
        """
        self._itemCount = itemCount
        self.refreshLabels()
    
    @Slot(str)
    def setItemsTitle( self, title ):
        """
        Sets the title that will be displayed when the items labels are rendered
        
        :param      title | <str>
        """
        self._itemsTitle = nativestring(title)
        self.refreshLabels()
    
    @Slot(int)
    def setPageCount( self, pageCount ):
        """
        Sets the number of pages that this widget holds.
        
        :param      pageCount | <int>
        """
        if ( pageCount == self._pageCount ):
            return
        
        pageCount = max(1, pageCount)
        
        self._pageCount = pageCount
        self._pagesSpinner.setMaximum(pageCount)
        self._pagesLabel.setText('of %i for ' % pageCount)
        
        if ( pageCount and self.currentPage() <= 0 ):
            self.setCurrentPage(1)
        
        elif ( pageCount < self.currentPage() ):
            self.setCurrentPage(pageCount)
        
        if ( not self.signalsBlocked() ):
            self.pageCountChanged.emit(pageCount)
        
        self._prevButton.setEnabled(self.currentPage() > 1)
        self._nextButton.setEnabled(self.currentPage() < pageCount)
    
    @Slot(int)
    def setPageSize( self, pageSize ):
        """
        Sets the number of items that should be visible in a page.  Setting the
        value to 0 will use all sizes
        
        :return     <int>
        """
        if self._pageSize == pageSize:
            return
        
        self._pageSize = pageSize
        
        # update the display size
        ssize = nativestring(pageSize)
        if ( ssize == '0' ):
            ssize = ''
        
        self._pageSizeCombo.blockSignals(True)
        index = self._pageSizeCombo.findText(ssize)
        self._pageSizeCombo.setCurrentIndex(index)
        self._pageSizeCombo.blockSignals(False)
    
    def setPageSizeOptions( self, options ):
        """
        Sets the options that will be displayed for this default size.
        
        :param      options | [<str>,. ..]
        """
        self._pageSizeCombo.blockSignals(True)
        self._pageSizeCombo.addItems(options)
        
        ssize = nativestring(self.pageSize())
        if ( ssize == '0' ):
            ssize = ''
        
        index = self._pageSizeCombo.findText()
        self._pageSizeCombo.setCurrentIndex(index)
        self._pageSizeCombo.blockSignals(False)
    
    x_itemsTitle = Property(str, itemsTitle, setItemsTitle)
    x_pageCount = Property(int, pageCount, setPageCount)
    x_pageSize = Property(int, pageSize, setPageSize)
    x_pageSizeOptions = Property(list, pageSizeOptions, setPageSizeOptions)
Example #16
0
class XLoaderWidget(QWidget):
    """ """
    Mode    = enum('Spinner', 'Progress')
    MOVIE   = None
    
    def __init__( self, parent = None, style='gray' ):
        super(XLoaderWidget, self).__init__( parent )
        
        # define properties
        self._currentMode       = None
        self._showSubProgress   = False
        
        self.setAttribute(Qt.WA_DeleteOnClose)
        
        # udpate the palette
        palette = self.palette()
        
        if style == 'white':
            palette.setColor( palette.Window, QColor(255, 255, 255, 180) )
        else:
            palette.setColor( palette.Window, QColor( 80, 80, 80, 180 ) )
        
        palette.setColor( palette.Base, Qt.gray )
        palette.setColor( palette.AlternateBase, Qt.lightGray )
        palette.setColor( palette.WindowText, Qt.gray )
        self.setPalette(palette)
        
        # create the movie label
        self._movieLabel = QLabel(self)
        self._movieLabel.setAlignment(Qt.AlignCenter)
        self._movieLabel.setMovie(XLoaderWidget.getMovie())
        self._movieLabel.setPalette(palette)
        
        self._smallMovieLabel = QLabel(self)
        self._smallMovieLabel.setAlignment(Qt.AlignCenter)
        self._smallMovieLabel.setMovie(XLoaderWidget.getMovie())
        self._smallMovieLabel.setPalette(palette)
        self._smallMovieLabel.hide()
        
        # create text label
        self._messageLabel = QLabel(self)
        self._messageLabel.setAlignment(Qt.AlignCenter)
        self._messageLabel.setText('Loading...')
        self._messageLabel.setPalette(palette)
        
        # create primary progress bar
        self._primaryProgressBar    = XLoaderProgressBar(self)
        self._subProgressBar        = XLoaderProgressBar(self)
        
        self._primaryProgressBar.setPalette(palette)
        self._subProgressBar.setPalette(palette)
        
        # create the loader widget
        self._loaderFrame = QFrame(self)
        self._loaderFrame.setFrameShape(QFrame.Box)
        self._loaderFrame.setAutoFillBackground(True)
        self._loaderFrame.setFixedWidth(160)
        self._loaderFrame.setFixedHeight(60)
        
        if style == 'white':
            palette.setColor(palette.Window, QColor('white'))
        else:
            palette.setColor(palette.Window, QColor(85, 85, 85))
        self._loaderFrame.setPalette(palette)
        
        layout = QVBoxLayout()
        layout.addWidget(self._movieLabel)
        layout.addWidget(self._primaryProgressBar)
        layout.addWidget(self._subProgressBar)
        layout.addStretch()
        layout.addWidget(self._messageLabel)
        self._loaderFrame.setLayout(layout)
        
        # set default properties
        self.setAutoFillBackground(True)
        
        # layout the controls
        layout = QVBoxLayout()
        layout.addStretch(1)
        layout.addWidget(self._loaderFrame)
        layout.addWidget(self._smallMovieLabel)
        layout.addStretch(1)
        
        hlayout = QHBoxLayout()
        hlayout.addStretch(1)
        hlayout.addLayout(layout)
        hlayout.addStretch(1)
        
        self.setLayout(hlayout)
        self.setCurrentMode(XLoaderWidget.Mode.Spinner)
        
        # create connections
    
    def currentMode( self ):
        """
        Returns the current mode that this loader's in.
        
        :return     <XLoaderWidget.Mode>
        """
        return self._currentMode
    
    def eventFilter( self, object, event ):
        """
        Resizes this widget with the parent when its resize event is triggered.
        
        :param      object | <QObject>
                    event  | <QEvent>
        
        :return     <bool> | consumed
        """
        if event.type() == event.Resize:
            self.resize(event.size())
            
        elif event.type() == event.Move:
            self.move(event.pos())
        
        elif event.type() == event.Close:
            self.setParent(None)
            self.deleteLater()
        
        return False
    
    def increment(self, amount=1):
        """
        Increments the main progress bar by amount.
        """
        self._primaryProgressBar.setValue(self.value() + amount)
        QApplication.instance().processEvents()
    
    def incrementSub(self, amount=1):
        """
        Increments the sub-progress bar by amount.
        """
        self._subProgressBar.setValue(self.subValue() + amount)
        QApplication.instance().processEvents()
    
    def message( self ):
        """
        Returns the current message being displayed in the loader.
        
        :return     <str>
        """
        return self._messageLabel.text()
    
    def movie(self):
        """
        Returns the movie linked with this loader.
        
        :return     <QMovie>
        """
        return self._movieLabel.movie()
    
    def resize(self, size):
        """
        Handles when the loader is too small for an area.
        
        :param      event | <QResizeEvent>
        """
        super(XLoaderWidget, self).resize(size)
        
        # show small loader
        if size.width() < self._loaderFrame.width() or \
           size.height() < self._loaderFrame.height():
            self._loaderFrame.hide()
            self._smallMovieLabel.show()
        
        # show regular loader
        else:
            self._loaderFrame.show()
            self._smallMovieLabel.hide()
    
    def subValue( self ):
        """
        Returns the value of the sub progress bar.
        
        :return     <int>
        """
        return self._subProgressBar.value()
    
    def setCurrentMode( self, mode ):
        """
        Sets what mode this loader will be in.
        
        :param      mode | <XLoaderWidget.Mode>
        """
        if ( mode == self._currentMode ):
            return
            
        self._currentMode = mode
        
        ajax = mode == XLoaderWidget.Mode.Spinner
        self._movieLabel.setVisible(ajax)
        self._primaryProgressBar.setVisible(not ajax)
        self._subProgressBar.setVisible(not ajax and self._showSubProgress)
    
    def setMessage( self, message ):
        """
        Sets the loading message to display.
        
        :param      message | <str>
        """
        self._messageLabel.setText(message)
    
    def setMovie( self, movie ):
        """
        Sets the movie for this loader to the inputed movie.
        
        :param      movie | <QMovie>
        """
        self._movieLabel.setMovie(movie)
        self._smallMovieLabel.setMovie(movie)
    
    def setTotal( self, amount ):
        """
        Sets the total amount for the main progress bar.
        
        :param      amount | <int>
        """
        self._primaryProgressBar.setValue(0)
        self._primaryProgressBar.setMaximum(amount)
        
        if amount:
            self.setCurrentMode(XLoaderWidget.Mode.Progress)
    
    def setSubTotal( self, amount ):
        """
        Sets the total value for the sub progress bar.
        
        :param      amount | <int>
        """
        self._subProgressBar.setValue(0)
        self._subProgressBar.setMaximum(amount)
        if amount:
            self.setShowSubProgress(True)
    
    def setSubValue( self, value ):
        """
        Sets the current value for the sub progress bar.
        
        :param      value | <int>
        """
        self._subProgressBar.setValue(value)
        
    def setShowSubProgress( self, state ):
        """
        Toggles whether or not the sub progress bar should be visible.
        
        :param      state | <bool>
        """
        ajax = self.currentMode() == XLoaderWidget.Mode.Spinner
        self._showSubProgress = state
        self._subProgressBar.setVisible(not ajax and state)
    
    def setValue(self, value):
        """
        Sets the current value for the primary progress bar.
        
        :param      value | <int>
        """
        self._primaryProgressBar.setValue(value)
    
    def showSubProgress( self ):
        """
        Returns whether or not the sub progress bar is visible when not in
        ajax mode.
        
        :return     <bool>
        """
        return self._showSubProgress
    
    def subValue( self ):
        """
        Returns the sub value for this loader.
        
        :return     <int>
        """
        return self._subProgressBar.value()
    
    def value( self ):
        """
        Returns the value for the primary progress bar.
        
        :return     <int>
        """
        return self._primaryProgressBar.value()
    
    @staticmethod
    def getMovie():
        """
        Returns the movie instance for the loader widget.
        
        :return     <QMovie>
        """
        if not XLoaderWidget.MOVIE:
            filename = projexui.resources.find('img/ajax_loader.gif')
            XLoaderWidget.MOVIE = QMovie()
            XLoaderWidget.MOVIE.setFileName(filename)
            XLoaderWidget.MOVIE.start()
        
        return XLoaderWidget.MOVIE
    
    @staticmethod
    def start(widget, processEvents=True, style=None, movie=None):
        """
        Starts a loader widget on the inputed widget.
        
        :param      widget          | <QWidget>
        
        :return     <XLoaderWidget>
        """
        if style is None:
            style = os.environ.get('PROJEXUI_LOADER_STYLE', 'gray')
        
        # there is a bug with the way the loader is handled in a splitter,
        # so bypass it
        parent = widget.parent()
        while isinstance(parent, QSplitter):
            parent = parent.parent()
        
        # retrieve the loader widget
        loader = getattr(widget, '_private_xloader_widget', None)
        if not loader:
            loader = XLoaderWidget(parent, style)
            
            # make sure that if the widget is destroyed, the loader closes
            widget.destroyed.connect(loader.deleteLater)
            
            setattr(widget, '_private_xloader_widget', loader)
            setattr(widget, '_private_xloader_count', 0)
            
            loader.move(widget.pos())
            if widget.isVisible():
                loader.show()
            
            if movie:
                loader.setMovie(movie)
            
            widget.installEventFilter(loader)
        else:
            count = getattr(widget, '_private_xloader_count', 0)
            setattr(widget, '_private_xloader_count', count + 1)
        
        loader.resize(widget.size())
        return loader
    
    @staticmethod
    def stop(widget, force=False):
        """
        Stops a loader widget on the inputed widget.
        
        :param      widget | <QWidget>
        """
        # make sure we have a widget to stop
        loader = getattr(widget, '_private_xloader_widget', None)
        if not loader:
            return
        
        # decrement the number of times this loader was created for the widget
        # to allow for stacked closure
        count = getattr(widget, '_private_xloader_count', 0)
        if force or count <= 1:
            # close out the loader widget
            setattr(widget, '_private_xloader_count', 0)
            setattr(widget, '_private_xloader_widget', None)
            
            loader.close()
            loader.setParent(None)
            loader.deleteLater()
        else:
            setattr(widget, '_private_xloader_count', count - 1)
    
    @staticmethod
    def stopAll(widget):
        """
        Stops all loader widgets from this parent down, cleaning out the \
        memory for them.
        
        :param      widget  | <QWidget>
        """
        for loader in widget.findChildren(XLoaderWidget):
            loader.setParent(None)
            loader.deleteLater()
Example #17
0
class XSplitterHandle(QSplitterHandle):
    CollapseDirection = enum('After', 'Before')

    def __init__(self, orientation, parent):
        super(XSplitterHandle, self).__init__(orientation, parent)

        # create a layout for the different buttons
        self._collapsed = False
        self._storedSizes = None

        self._collapseBefore = QToolButton(self)
        self._resizeGrip = QLabel(self)
        self._collapseAfter = QToolButton(self)

        self._collapseBefore.setAutoRaise(True)
        self._collapseAfter.setAutoRaise(True)

        self._collapseBefore.setCursor(Qt.ArrowCursor)
        self._collapseAfter.setCursor(Qt.ArrowCursor)

        # define the layout
        layout = QBoxLayout(QBoxLayout.LeftToRight, self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addStretch(1)
        layout.addWidget(self._collapseBefore)
        layout.addWidget(self._resizeGrip)
        layout.addWidget(self._collapseAfter)
        layout.addStretch(1)
        self.setLayout(layout)

        # set the orientation to start with
        self.setOrientation(orientation)

        # create connections
        self._collapseAfter.clicked.connect(self.toggleCollapseAfter)
        self._collapseBefore.clicked.connect(self.toggleCollapseBefore)

    def collapse(self, direction):
        """
        Collapses this splitter handle before or after other widgets based on \
        the inputed CollapseDirection.
        
        :param      direction | <XSplitterHandle.CollapseDirection>
        
        :return     <bool> | success
        """
        if (self.isCollapsed()):
            return False

        splitter = self.parent()
        if (not splitter):
            return False

        sizes = splitter.sizes()
        handles = [splitter.handle(i) for i in range(len(sizes))]
        index = handles.index(self)

        self.markCollapsed(direction, sizes)

        # determine the sizes to use based on the direction
        if (direction == XSplitterHandle.CollapseDirection.Before):
            sizes = [0 for i in range(i)] + sizes[i + 1:]
        else:
            sizes = sizes[:i] + [0 for i in range(i, len(sizes))]

        splitter.setSizes(sizes)
        return True

    def collapseAfter(self, handle):
        """
        Collapses the splitter after the inputed handle.
        
        :param      handle | <XSplitterHandle>
        """
        self.setUpdatesEnabled(False)

        # collapse all items after the current handle
        if (handle.isCollapsed()):
            self.setSizes(handle.restoreSizes())

        found = False
        sizes = self.sizes()

        handle.storeSizes(sizes)

        for c in range(self.count()):
            if (self.handle(c) == handle):
                found = True

            if (found):
                sizes[c] = 0

        self.setSizes(sizes)
        self.update()

        self.setUpdatesEnabled(True)

    def collapseBefore(self, handle):
        """
        Collapses the splitter before the inputed handle.
        
        :param      handle | <XSplitterHandle>
        """
        self.setUpdatesEnabled(False)

        # collapse all items after the current handle
        if (handle.isCollapsed()):
            self.setSizes(handle.restoreSizes())

        # collapse all items before the current handle
        found = False
        sizes = self.sizes()

        handle.storeSizes(sizes)

        for c in range(self.count()):
            if (self.handle(c) == handle):
                break

            sizes[c] = 0

        self.setSizes(sizes)
        self.setUpdatesEnabled(True)

    def isCollapsed(self):
        """
        Returns whether or not this widget is collapsed.
        
        :return     <bool>
        """
        return self._collapsed

    def markCollapsed(self, direction, sizes):
        """
        Updates the interface to reflect that the splitter is collapsed.
        
        :param      direction | <XSplitterHandle.CollapseDirection>
                    sizes     | [<int>, ..]
        """
        self._collapsed = True
        self._storedSizes = sizes[:]

        if (direction == XSplitterHandle.CollapseDirection.Before):
            if (self.orientation() == Qt.Horizontal):
                self._collapseAfter.setArrowType(Qt.RightArrow)
                self._collapseBefore.setArrowType(Qt.RightArrow)
            else:
                self._collapseAfter.setArrowType(Qt.DownArrow)
                self._collapseBefore.setArrowType(Qt.DownArrow)
        else:
            if (self.orientation() == Qt.Horizontal):
                self._collapseAfter.setArrowType(Qt.LeftArrow)
                self._collapseBefore.setArrowType(Qt.LeftArrow)
            else:
                self._collapseAfter.setArrowType(Qt.UpArrow)
                self._collapseAfter.setArrowType(Qt.UpArrow)

    def paintEvent(self, event):
        """
        Overloads the paint event to handle drawing the splitter lines.
        
        :param      event | <QPaintEvent>
        """
        lines = []
        count = 20

        # calculate the lines
        if (self.orientation() == Qt.Vertical):
            x = self._resizeGrip.pos().x()
            h = self.height()
            spacing = int(float(self._resizeGrip.width()) / count)

            for i in range(count):
                lines.append(QLine(x, 0, x, h))
                x += spacing
        else:
            y = self._resizeGrip.pos().y()
            w = self.width()
            spacing = int(float(self._resizeGrip.height()) / count)

            for i in range(count):
                lines.append(QLine(0, y, w, y))
                y += spacing

        # draw the lines
        with XPainter(self) as painter:
            pal = self.palette()
            painter.setPen(pal.color(pal.Window).darker(120))
            painter.drawLines(lines)

    def setOrientation(self, orientation):
        """
        Sets the orientation for this handle and updates the widgets linked \
        with it.
        
        :param      orientation | <Qt.Orientation>
        """
        super(XSplitterHandle, self).setOrientation(orientation)

        if (orientation == Qt.Vertical):
            self.layout().setDirection(QBoxLayout.LeftToRight)

            # update the widgets
            self._collapseBefore.setFixedSize(30, 10)
            self._collapseAfter.setFixedSize(30, 10)
            self._resizeGrip.setFixedSize(60, 10)

            self._collapseBefore.setArrowType(Qt.UpArrow)
            self._collapseAfter.setArrowType(Qt.DownArrow)

        elif (orientation == Qt.Horizontal):
            self.layout().setDirection(QBoxLayout.TopToBottom)

            # update the widgets
            self._collapseBefore.setFixedSize(10, 30)
            self._collapseAfter.setFixedSize(10, 30)
            self._resizeGrip.setFixedSize(10, 60)

            self._collapseBefore.setArrowType(Qt.LeftArrow)
            self._collapseAfter.setArrowType(Qt.RightArrow)

    def uncollapse(self):
        """
        Uncollapses the splitter this handle is associated with by restoring \
        its sizes from before the collapse occurred.
        
        :return     <bool> | changed
        """
        if (not self.isCollapsed()):
            return False

        self.parent().setSizes(self._storedSizes)
        self.unmarkCollapsed()

        return True

    def unmarkCollapsed(self):
        """
        Unmarks this splitter as being in a collapsed state, clearing any \
        collapsed information.
        """
        if (not self.isCollapsed()):
            return

        self._collapsed = False
        self._storedSizes = None

        if (self.orientation() == Qt.Vertical):
            self._collapseBefore.setArrowType(Qt.UpArrow)
            self._collapseAfter.setArrowType(Qt.DownArrow)
        else:
            self._collapseBefore.setArrowType(Qt.LeftArrow)
            self._collapseAfter.setArrowType(Qt.RightArrow)

    def toggleCollapseAfter(self):
        """
        Collapses the splitter after this handle.
        """
        if (self.isCollapsed()):
            self.uncollapse()
        else:
            self.collapse(XSplitterHandle.CollapseDirection.After)

    def toggleCollapseBefore(self):
        """
        Collapses the splitter before this handle.
        """
        if (self.isCollapsed()):
            self.uncollapse()
        else:
            self.collapse(XSplitterHandle.CollapseDirection.Before)
Example #18
0
 def rebuild( self ):
     """
     Rebuilds the interface for this widget based on the current model.
     """
     self.setUpdatesEnabled(False)
     self.blockSignals(True)
     
     # clear out all the subwidgets for this widget
     for child in self.findChildren(QObject):
         child.setParent(None)
         child.deleteLater()
     
     # load up all the interface for this widget
     schema = self.schema()
     if ( schema ):
         self.setEnabled(True)
         
         uifile = self.uiFile()
         
         # load a user defined file
         if ( uifile ):
             projexui.loadUi('', self, uifile)
             
             for widget in self.findChildren(XOrbColumnEdit):
                 columnName = widget.columnName()
                 column     = schema.column(columnName)
                 
                 if ( column ):
                     widget.setColumn(column)
                 else:
                     logger.debug('%s is not a valid column of %s' % \
                                  (columnName, schema.name()))
         
         # dynamically load files
         else:
             layout = QFormLayout()
             layout.setContentsMargins(0, 0, 0, 0)
             columns = schema.columns()
             columns.sort(key = lambda x: x.displayName())
             
             record = self.record()
             
             for column in columns:
                 # ignore protected columns
                 if ( column.name().startswith('_') ):
                     continue
                 
                 label   = column.displayName()
                 coltype = column.columnType()
                 name    = column.name()
                 
                 # create the column edit widget
                 widget  = XOrbColumnEdit(self)
                 widget.setObjectName('ui_' + name)
                 widget.setColumnName(name)
                 widget.setColumnType(coltype)
                 widget.setColumn(column)
                 
                 layout.addRow(QLabel(label, self), widget)
             
             self.setLayout(layout)
             self.adjustSize()
             
             self.setWindowTitle('Edit %s' % schema.name())
     else:
         self.setEnabled(False)
     
     self.setUpdatesEnabled(True)
     self.blockSignals(False)
Example #19
0
 def __init__( self, parent = None, style='gray' ):
     super(XLoaderWidget, self).__init__( parent )
     
     # define properties
     self._currentMode       = None
     self._showSubProgress   = False
     
     self.setAttribute(Qt.WA_DeleteOnClose)
     
     # udpate the palette
     palette = self.palette()
     
     if style == 'white':
         palette.setColor( palette.Window, QColor(255, 255, 255, 180) )
     else:
         palette.setColor( palette.Window, QColor( 80, 80, 80, 180 ) )
     
     palette.setColor( palette.Base, Qt.gray )
     palette.setColor( palette.AlternateBase, Qt.lightGray )
     palette.setColor( palette.WindowText, Qt.gray )
     self.setPalette(palette)
     
     # create the movie label
     self._movieLabel = QLabel(self)
     self._movieLabel.setAlignment(Qt.AlignCenter)
     self._movieLabel.setMovie(XLoaderWidget.getMovie())
     self._movieLabel.setPalette(palette)
     
     self._smallMovieLabel = QLabel(self)
     self._smallMovieLabel.setAlignment(Qt.AlignCenter)
     self._smallMovieLabel.setMovie(XLoaderWidget.getMovie())
     self._smallMovieLabel.setPalette(palette)
     self._smallMovieLabel.hide()
     
     # create text label
     self._messageLabel = QLabel(self)
     self._messageLabel.setAlignment(Qt.AlignCenter)
     self._messageLabel.setText('Loading...')
     self._messageLabel.setPalette(palette)
     
     # create primary progress bar
     self._primaryProgressBar    = XLoaderProgressBar(self)
     self._subProgressBar        = XLoaderProgressBar(self)
     
     self._primaryProgressBar.setPalette(palette)
     self._subProgressBar.setPalette(palette)
     
     # create the loader widget
     self._loaderFrame = QFrame(self)
     self._loaderFrame.setFrameShape(QFrame.Box)
     self._loaderFrame.setAutoFillBackground(True)
     self._loaderFrame.setFixedWidth(160)
     self._loaderFrame.setFixedHeight(60)
     
     if style == 'white':
         palette.setColor(palette.Window, QColor('white'))
     else:
         palette.setColor(palette.Window, QColor(85, 85, 85))
     self._loaderFrame.setPalette(palette)
     
     layout = QVBoxLayout()
     layout.addWidget(self._movieLabel)
     layout.addWidget(self._primaryProgressBar)
     layout.addWidget(self._subProgressBar)
     layout.addStretch()
     layout.addWidget(self._messageLabel)
     self._loaderFrame.setLayout(layout)
     
     # set default properties
     self.setAutoFillBackground(True)
     
     # layout the controls
     layout = QVBoxLayout()
     layout.addStretch(1)
     layout.addWidget(self._loaderFrame)
     layout.addWidget(self._smallMovieLabel)
     layout.addStretch(1)
     
     hlayout = QHBoxLayout()
     hlayout.addStretch(1)
     hlayout.addLayout(layout)
     hlayout.addStretch(1)
     
     self.setLayout(hlayout)
     self.setCurrentMode(XLoaderWidget.Mode.Spinner)
Example #20
0
class XSplitterHandle(QSplitterHandle):
    CollapseDirection = enum('After', 'Before')
    
    def __init__( self, orientation, parent ):
        super(XSplitterHandle, self).__init__( orientation, parent )
        
        # create a layout for the different buttons
        self._collapsed      = False
        self._storedSizes    = None
        
        self._collapseBefore = QToolButton(self)
        self._resizeGrip     = QLabel(self)
        self._collapseAfter  = QToolButton(self)
        
        self._collapseBefore.setAutoRaise(True)
        self._collapseAfter.setAutoRaise(True)
        
        self._collapseBefore.setCursor(Qt.ArrowCursor)
        self._collapseAfter.setCursor(Qt.ArrowCursor)
        
        # define the layout
        layout = QBoxLayout(QBoxLayout.LeftToRight, self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addStretch(1)
        layout.addWidget(self._collapseBefore)
        layout.addWidget(self._resizeGrip)
        layout.addWidget(self._collapseAfter)
        layout.addStretch(1)
        self.setLayout(layout)
        
        # set the orientation to start with
        self.setOrientation(orientation)
        
        # create connections
        self._collapseAfter.clicked.connect(  self.toggleCollapseAfter )
        self._collapseBefore.clicked.connect( self.toggleCollapseBefore )
    
    def collapse( self, direction ):
        """
        Collapses this splitter handle before or after other widgets based on \
        the inputed CollapseDirection.
        
        :param      direction | <XSplitterHandle.CollapseDirection>
        
        :return     <bool> | success
        """
        if ( self.isCollapsed() ):
            return False
        
        splitter = self.parent()
        if ( not splitter ):
            return False
        
        sizes   = splitter.sizes()
        handles = [splitter.handle(i) for i in range(len(sizes))]
        index   = handles.index(self)
        
        self.markCollapsed(direction, sizes)
        
        # determine the sizes to use based on the direction
        if ( direction == XSplitterHandle.CollapseDirection.Before ):
            sizes = [0 for i in range(i)] + sizes[i+1:]
        else:
            sizes = sizes[:i] + [0 for i in range(i, len(sizes))]
        
        splitter.setSizes(sizes)
        return True
        
    def collapseAfter( self, handle ):
        """
        Collapses the splitter after the inputed handle.
        
        :param      handle | <XSplitterHandle>
        """
        self.setUpdatesEnabled(False)
        
        # collapse all items after the current handle
        if ( handle.isCollapsed() ):
            self.setSizes(handle.restoreSizes())
            
        found = False
        sizes = self.sizes()
        
        handle.storeSizes(sizes)
        
        for c in range(self.count()):
            if ( self.handle(c) == handle ):
                found = True
            
            if ( found ):
                sizes[c] = 0
        
        self.setSizes(sizes)
        self.update()
        
        self.setUpdatesEnabled(True)
    
    def collapseBefore( self, handle ):
        """
        Collapses the splitter before the inputed handle.
        
        :param      handle | <XSplitterHandle>
        """
        self.setUpdatesEnabled(False)
        
        # collapse all items after the current handle
        if ( handle.isCollapsed() ):
            self.setSizes(handle.restoreSizes())
            
        # collapse all items before the current handle
        found = False
        sizes = self.sizes()
        
        handle.storeSizes(sizes)
        
        for c in range(self.count()):
            if ( self.handle(c) == handle ):
                break
            
            sizes[c] = 0
        
        self.setSizes(sizes)
        self.setUpdatesEnabled(True)
    
    def isCollapsed( self ):
        """
        Returns whether or not this widget is collapsed.
        
        :return     <bool>
        """
        return self._collapsed
    
    def markCollapsed( self, direction, sizes ):
        """
        Updates the interface to reflect that the splitter is collapsed.
        
        :param      direction | <XSplitterHandle.CollapseDirection>
                    sizes     | [<int>, ..]
        """
        self._collapsed = True
        self._storedSizes = sizes[:]
        
        if ( direction == XSplitterHandle.CollapseDirection.Before ):
            if ( self.orientation() == Qt.Horizontal ):
                self._collapseAfter.setArrowType( Qt.RightArrow )
                self._collapseBefore.setArrowType( Qt.RightArrow )
            else:
                self._collapseAfter.setArrowType( Qt.DownArrow )
                self._collapseBefore.setArrowType( Qt.DownArrow )
        else:
            if ( self.orientation() == Qt.Horizontal ):
                self._collapseAfter.setArrowType( Qt.LeftArrow )
                self._collapseBefore.setArrowType( Qt.LeftArrow )
            else:
                self._collapseAfter.setArrowType( Qt.UpArrow )
                self._collapseAfter.setArrowType( Qt.UpArrow )
        
    def paintEvent( self, event ):
        """
        Overloads the paint event to handle drawing the splitter lines.
        
        :param      event | <QPaintEvent>
        """
        lines = []
        count = 20
        
        # calculate the lines
        if ( self.orientation() == Qt.Vertical ):
            x = self._resizeGrip.pos().x()
            h = self.height()
            spacing = int(float(self._resizeGrip.width()) / count)
            
            for i in range(count):
                lines.append(QLine(x, 0, x, h))
                x += spacing
        else:
            y = self._resizeGrip.pos().y()
            w = self.width()
            spacing = int(float(self._resizeGrip.height()) / count)
            
            for i in range(count):
                lines.append(QLine(0, y, w, y))
                y += spacing
            
        # draw the lines
        with XPainter(self) as painter:
            pal = self.palette()
            painter.setPen(pal.color(pal.Window).darker(120))
            painter.drawLines(lines)
    
    def setOrientation( self, orientation ):
        """
        Sets the orientation for this handle and updates the widgets linked \
        with it.
        
        :param      orientation | <Qt.Orientation>
        """
        super(XSplitterHandle, self).setOrientation(orientation)
        
        if ( orientation == Qt.Vertical ):
            self.layout().setDirection( QBoxLayout.LeftToRight )
            
            # update the widgets
            self._collapseBefore.setFixedSize(30, 10)
            self._collapseAfter.setFixedSize(30, 10)
            self._resizeGrip.setFixedSize(60, 10)
            
            self._collapseBefore.setArrowType(Qt.UpArrow)
            self._collapseAfter.setArrowType(Qt.DownArrow)
            
        elif ( orientation == Qt.Horizontal ):
            self.layout().setDirection( QBoxLayout.TopToBottom )
            
            # update the widgets
            self._collapseBefore.setFixedSize(10, 30)
            self._collapseAfter.setFixedSize(10, 30)
            self._resizeGrip.setFixedSize(10, 60)
            
            self._collapseBefore.setArrowType(Qt.LeftArrow)
            self._collapseAfter.setArrowType(Qt.RightArrow)
    
    def uncollapse( self ):
        """
        Uncollapses the splitter this handle is associated with by restoring \
        its sizes from before the collapse occurred.
        
        :return     <bool> | changed
        """
        if ( not self.isCollapsed() ):
            return False
        
        self.parent().setSizes(self._storedSizes)
        self.unmarkCollapsed()
        
        return True
    
    def unmarkCollapsed( self ):
        """
        Unmarks this splitter as being in a collapsed state, clearing any \
        collapsed information.
        """
        if ( not self.isCollapsed() ):
            return
        
        self._collapsed     = False
        self._storedSizes   = None
        
        if ( self.orientation() == Qt.Vertical ):
            self._collapseBefore.setArrowType( Qt.UpArrow )
            self._collapseAfter.setArrowType(  Qt.DownArrow )
        else:
            self._collapseBefore.setArrowType( Qt.LeftArrow )
            self._collapseAfter.setArrowType(  Qt.RightArrow )
    
    def toggleCollapseAfter( self ):
        """
        Collapses the splitter after this handle.
        """
        if ( self.isCollapsed() ):
            self.uncollapse()
        else:
            self.collapse( XSplitterHandle.CollapseDirection.After )
    
    def toggleCollapseBefore( self ):
        """
        Collapses the splitter before this handle.
        """
        if ( self.isCollapsed() ):
            self.uncollapse()
        else:
            self.collapse( XSplitterHandle.CollapseDirection.Before )
Example #21
0
 def showToolTip( text,
                  point      = None,
                  anchor     = None,
                  parent     = None,
                  background = None,
                  foreground = None,
                  key        = None,
                  seconds    = 5 ):
     """
     Displays a popup widget as a tooltip bubble.
     
     :param      text        | <str>
                 point       | <QPoint> || None
                 anchor      | <XPopupWidget.Mode.Anchor> || None
                 parent      | <QWidget> || None
                 background  | <QColor> || None
                 foreground  | <QColor> || None
                 key         | <str> || None
                 seconds     | <int>
     """
     if point is None:
         point = QCursor.pos()
         
     if parent is None:
         parent = QApplication.activeWindow()
     
     if anchor is None and parent is None:
         anchor = XPopupWidget.Anchor.TopCenter
     
     # create a new tooltip widget
     widget = XPopupWidget(parent)
     widget.setToolTipMode()
     widget.setResizable(False)
     
     # create the tooltip label
     label = QLabel(text, widget)
     label.setOpenExternalLinks(True)
     label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
     label.setMargin(3)
     label.setIndent(3)
     label.adjustSize()
 
     widget.setCentralWidget(label)
     
     # update the tip
     label.adjustSize()
     widget.adjustSize()
     
     palette = widget.palette()
     if not background:
         background = palette.color(palette.ToolTipBase)
     if not foreground:
         foreground = palette.color(palette.ToolTipText)
     
     palette.setColor(palette.Window,     QColor(background))
     palette.setColor(palette.WindowText, QColor(foreground))
     widget.setPalette(palette)
     widget.centralWidget().setPalette(palette)
     
     if anchor is None:
         widget.setAutoCalculateAnchor(True)
     else:
         widget.setAnchor(anchor)
     
     widget.setAutoCloseOnFocusOut(True)
     widget.setAttribute(Qt.WA_DeleteOnClose)
     widget.popup(point)
     widget.startTimer(1000 * seconds)
     
     return widget
Example #22
0
    def addSection(self, section):
        """
        Adds a section to this menu.  A section will create a label for the
        menu to separate sections of the menu out.
        
        :param      section | <str>
        """
        label = QLabel(section, self)
        label.setMinimumHeight(self.titleHeight())

        # setup font
        font = label.font()
        font.setBold(True)

        # setup palette
        palette = label.palette()
        palette.setColor(palette.WindowText, palette.color(palette.Mid))

        # setup label
        label.setFont(font)
        label.setAutoFillBackground(True)
        label.setPalette(palette)

        # create the widget action
        action = QWidgetAction(self)
        action.setDefaultWidget(label)
        self.addAction(action)

        return action
Example #23
0
 def addSection(self, section):
     """
     Adds a section to this menu.  A section will create a label for the
     menu to separate sections of the menu out.
     
     :param      section | <str>
     """
     label = QLabel(section, self)
     label.setMinimumHeight(self.titleHeight())
     
     # setup font
     font = label.font()
     font.setBold(True)
     
     # setup palette
     palette = label.palette()
     palette.setColor(palette.WindowText, palette.color(palette.Mid))
     
     # setup label
     label.setFont(font)
     label.setAutoFillBackground(True)
     label.setPalette(palette)
     
     # create the widget action
     action = QWidgetAction(self)
     action.setDefaultWidget(label)
     self.addAction(action)
     
     return action
Example #24
0
class XPagesWidget(QWidget):
    """ """
    currentPageChanged = Signal(int)
    pageSizeChanged = Signal(int)
    pageCountChanged = Signal(int)

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

        # define custom properties
        self._currentPage = 1
        self._pageCount = 10
        self._itemCount = 0
        self._pageSize = 50
        self._itemsTitle = 'items'

        self._pagesSpinner = QSpinBox()
        self._pagesSpinner.setMinimum(1)
        self._pagesSpinner.setMaximum(10)

        self._pageSizeCombo = XComboBox(self)
        self._pageSizeCombo.setHint('all')
        self._pageSizeCombo.addItems(['', '25', '50', '75', '100'])
        self._pageSizeCombo.setCurrentIndex(2)

        self._nextButton = QToolButton(self)
        self._nextButton.setAutoRaise(True)
        self._nextButton.setArrowType(Qt.RightArrow)
        self._nextButton.setFixedWidth(16)

        self._prevButton = QToolButton(self)
        self._prevButton.setAutoRaise(True)
        self._prevButton.setArrowType(Qt.LeftArrow)
        self._prevButton.setFixedWidth(16)
        self._prevButton.setEnabled(False)

        self._pagesLabel = QLabel('of 10 for ', self)
        self._itemsLabel = QLabel(' items per page', self)

        # define the interface
        layout = QHBoxLayout()
        layout.addWidget(QLabel('Page', self))
        layout.addWidget(self._prevButton)
        layout.addWidget(self._pagesSpinner)
        layout.addWidget(self._nextButton)
        layout.addWidget(self._pagesLabel)
        layout.addWidget(self._pageSizeCombo)
        layout.addWidget(self._itemsLabel)
        layout.addStretch(1)

        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)

        self.setLayout(layout)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

        # create connections
        self._pageSizeCombo.currentIndexChanged.connect(self.pageSizePicked)
        self._nextButton.clicked.connect(self.gotoNext)
        self._prevButton.clicked.connect(self.gotoPrevious)
        self._pagesSpinner.editingFinished.connect(self.assignCurrentPage)

    def assignCurrentPage(self):
        """
        Assigns the page for the spinner to be current.
        """
        self.setCurrentPage(self._pagesSpinner.value())

    def currentPage(self):
        """
        Reutrns the current page for this widget.
        
        :return     <int>
        """
        return self._currentPage

    @Slot()
    def gotoFirst(self):
        """
        Goes to the first page.
        
        :sa     setCurrentPage
        """
        self.setCurrentPage(1)

    @Slot()
    def gotoLast(self):
        """
        Goes to the last page.
        
        :sa     setCurrentPage
        """
        self.setCurrentPage(self.pageCount())

    @Slot()
    def gotoNext(self):
        """
        Goes to the next page.
        
        :sa     setCurrentPage
        """
        next_page = self.currentPage() + 1
        if (next_page > self.pageCount()):
            return

        self.setCurrentPage(next_page)

    @Slot()
    def gotoPrevious(self):
        """
        Goes to the previous page.
        
        :sa     setCurrentPage
        """
        prev_page = self.currentPage() - 1
        if (prev_page == 0):
            return

        self.setCurrentPage(prev_page)

    def itemCount(self):
        """
        Returns the total number of items this widget holds.  If no item count
        is defined, it will not be displayed in the label, otherwise it will
        show.
        
        :return     <int>
        """
        return self._itemCount

    def itemsTitle(self):
        """
        Returns the items title for this instance.
        
        :return     <str>
        """
        return self._itemsTitle

    def pageCount(self):
        """
        Returns the number of pages that this widget holds.
        
        :return     <int>
        """
        return self._pageCount

    def pageSize(self):
        """
        Returns the number of items that should be visible in a page.
        
        :return     <int>
        """
        return self._pageSize

    def pageSizeOptions(self):
        """
        Returns the list of options that will be displayed for this default
        size options.
        
        :return     [<str>, ..]
        """
        return map(str, self._pageSizeCombo.items())

    def pageSizePicked(self, pageSize):
        """
        Updates when the user picks a page size.
        
        :param      pageSize | <str>
        """
        try:
            pageSize = int(self._pageSizeCombo.currentText())
        except ValueError:
            pageSize = 0

        self.setPageSize(pageSize)
        self.pageSizeChanged.emit(pageSize)

    def refreshLabels(self):
        """
        Refreshes the labels to display the proper title and count information.
        """
        itemCount = self.itemCount()
        title = self.itemsTitle()

        if (not itemCount):
            self._itemsLabel.setText(' %s per page' % title)
        else:
            msg = ' %s per page, %i %s total' % (title, itemCount, title)
            self._itemsLabel.setText(msg)

    @Slot(int)
    def setCurrentPage(self, pageno):
        """
        Sets the current page for this widget to the inputed page.
        
        :param      pageno | <int>
        """
        if (pageno == self._currentPage):
            return

        if (pageno <= 0):
            pageno = 1

        self._currentPage = pageno

        self._prevButton.setEnabled(pageno > 1)
        self._nextButton.setEnabled(pageno < self.pageCount())

        self._pagesSpinner.blockSignals(True)
        self._pagesSpinner.setValue(pageno)
        self._pagesSpinner.blockSignals(False)

        if (not self.signalsBlocked()):
            self.currentPageChanged.emit(pageno)

    @Slot(int)
    def setItemCount(self, itemCount):
        """
        Sets the item count for this page to the inputed value.
        
        :param      itemCount | <int>
        """
        self._itemCount = itemCount
        self.refreshLabels()

    @Slot(str)
    def setItemsTitle(self, title):
        """
        Sets the title that will be displayed when the items labels are rendered
        
        :param      title | <str>
        """
        self._itemsTitle = nativestring(title)
        self.refreshLabels()

    @Slot(int)
    def setPageCount(self, pageCount):
        """
        Sets the number of pages that this widget holds.
        
        :param      pageCount | <int>
        """
        if (pageCount == self._pageCount):
            return

        pageCount = max(1, pageCount)

        self._pageCount = pageCount
        self._pagesSpinner.setMaximum(pageCount)
        self._pagesLabel.setText('of %i for ' % pageCount)

        if (pageCount and self.currentPage() <= 0):
            self.setCurrentPage(1)

        elif (pageCount < self.currentPage()):
            self.setCurrentPage(pageCount)

        if (not self.signalsBlocked()):
            self.pageCountChanged.emit(pageCount)

        self._prevButton.setEnabled(self.currentPage() > 1)
        self._nextButton.setEnabled(self.currentPage() < pageCount)

    @Slot(int)
    def setPageSize(self, pageSize):
        """
        Sets the number of items that should be visible in a page.  Setting the
        value to 0 will use all sizes
        
        :return     <int>
        """
        if self._pageSize == pageSize:
            return

        self._pageSize = pageSize

        # update the display size
        ssize = nativestring(pageSize)
        if (ssize == '0'):
            ssize = ''

        self._pageSizeCombo.blockSignals(True)
        index = self._pageSizeCombo.findText(ssize)
        self._pageSizeCombo.setCurrentIndex(index)
        self._pageSizeCombo.blockSignals(False)

    def setPageSizeOptions(self, options):
        """
        Sets the options that will be displayed for this default size.
        
        :param      options | [<str>,. ..]
        """
        self._pageSizeCombo.blockSignals(True)
        self._pageSizeCombo.addItems(options)

        ssize = nativestring(self.pageSize())
        if (ssize == '0'):
            ssize = ''

        index = self._pageSizeCombo.findText()
        self._pageSizeCombo.setCurrentIndex(index)
        self._pageSizeCombo.blockSignals(False)

    x_itemsTitle = Property(str, itemsTitle, setItemsTitle)
    x_pageCount = Property(int, pageCount, setPageCount)
    x_pageSize = Property(int, pageSize, setPageSize)
    x_pageSizeOptions = Property(list, pageSizeOptions, setPageSizeOptions)
Example #25
0
class XPushButton(QPushButton):
    def __init__(self, *args, **kwds):
        super(XPushButton, self).__init__(*args, **kwds)
        
        # sets whether or not this button will display rich text
        self._showRichText  = False
        self._richTextLabel = None
        self._text          = ''
    
    def eventFilter(self, object, event):
        """
        Ignore all events for the text label.
        
        :param      object | <QObject>
                    event  | <QEvent>
        """
        if object == self._richTextLabel:
            if event.type() in (event.MouseButtonPress,
                                event.MouseMove,
                                event.MouseButtonRelease,
                                event.MouseButtonDblClick):
                event.ignore()
                return True
        return False
    
    def resizeEvent(self, event):
        """
        Overloads the resize event to auto-resize the rich text label to the
        size of this QPushButton.
        
        :param      event | <QResizeEvent>
        """
        super(XPushButton, self).resizeEvent(event)
        
        if self._richTextLabel:
            self._richTextLabel.resize(event.size())
        
    def richTextLabel(self):
        """
        Returns the label that is used for drawing the rich text to this button.
        
        :return     <QLabel>
        """
        if not self._richTextLabel:
            self._richTextLabel = QLabel(self)
            self._richTextLabel.installEventFilter(self)
            self._richTextLabel.setMargin(10)
        return self._richTextLabel
    
    def setShowRichText(self, state):
        """
        Sets whether or not to display rich text for this button.
        
        :param      state | <bool>
        """
        self._showRichText = state
        text = self.text()
        
        if state:
            label = self.richTextLabel()
            label.setText(text)
            label.show()
            super(XPushButton, self).setText('')
        else:
            if self._richTextLabel:
                self._richTextLabel.hide()
            
            super(XPushButton, self).setText(text)
    
    def setText(self, text):
        """
        Sets the text for this button.  If it is set to show rich text, then
        it will update the label text, leaving the root button text blank, 
        otherwise it will update the button.
        
        :param      text | <str>
        """
        self._text = nativestring(text)
        if self.showRichText():
            self.richTextLabel().setText(text)
        else:
            super(XPushButton, self).setText(text)
    
    def showRichText(self):
        """
        Returns whether or not rich text is visible for this button.
        
        :return     <bool>
        """
        return self._showRichText
    
    def text(self):
        """
        Returns the source text for this button.
        
        :return     <str>
        """
        return self._text

    x_showRichText = Property(bool, showRichText, setShowRichText)
Example #26
0
    def showToolTip(text,
                    point=None,
                    anchor=None,
                    parent=None,
                    background=None,
                    foreground=None,
                    key=None,
                    seconds=5):
        """
        Displays a popup widget as a tooltip bubble.
        
        :param      text        | <str>
                    point       | <QPoint> || None
                    anchor      | <XPopupWidget.Mode.Anchor> || None
                    parent      | <QWidget> || None
                    background  | <QColor> || None
                    foreground  | <QColor> || None
                    key         | <str> || None
                    seconds     | <int>
        """
        if point is None:
            point = QCursor.pos()

        if parent is None:
            parent = QApplication.activeWindow()

        if anchor is None and parent is None:
            anchor = XPopupWidget.Anchor.TopCenter

        # create a new tooltip widget
        widget = XPopupWidget(parent)
        widget.setToolTipMode()
        widget.setResizable(False)

        # create the tooltip label
        label = QLabel(text, widget)
        label.setOpenExternalLinks(True)
        label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
        label.setMargin(3)
        label.setIndent(3)
        label.adjustSize()

        widget.setCentralWidget(label)

        # update the tip
        label.adjustSize()
        widget.adjustSize()

        palette = widget.palette()
        if not background:
            background = palette.color(palette.ToolTipBase)
        if not foreground:
            foreground = palette.color(palette.ToolTipText)

        palette.setColor(palette.Window, QColor(background))
        palette.setColor(palette.WindowText, QColor(foreground))
        widget.setPalette(palette)
        widget.centralWidget().setPalette(palette)

        if anchor is None:
            widget.setAutoCalculateAnchor(True)
        else:
            widget.setAnchor(anchor)

        widget.setAutoCloseOnFocusOut(True)
        widget.setAttribute(Qt.WA_DeleteOnClose)
        widget.popup(point)
        widget.startTimer(1000 * seconds)

        return widget
    def rebuild(self):
        """
        Rebuilds the data associated with this filter widget.
        """
        table = self.tableType()
        form = nativestring(self.filterFormat())

        if not table and form:
            if self.layout().count() == 0:
                self.layout().addWidget(QLabel(form, self))
            else:
                self.layout().itemAt(0).widget().setText(form)
            return

        elif not form:
            return

        for child in self.findChildren(QWidget):
            child.close()
            child.setParent(None)
            child.deleteLater()

        self.setUpdatesEnabled(False)
        schema = table.schema()

        vlayout = self.layout()
        for i in range(vlayout.count()):
            vlayout.takeAt(0)

        self._plugins = []
        for line in form.split('\n'):
            row = QHBoxLayout()
            row.setContentsMargins(0, 0, 0, 0)
            row.setSpacing(0)

            for label, lookup in FORMAT_SPLITTER.findall(line):
                # create the label
                lbl = QLabel(label, self)
                row.addWidget(lbl)

                # create the query plugin
                opts = lookup.split(':')
                if len(opts) == 1:
                    opts.append('is')

                column = schema.column(opts[0])
                if not column:
                    continue

                plugin = self.pluginFactory().plugin(column)
                if not plugin:
                    continue

                editor = plugin.createEditor(self, column, opts[1], None)
                if editor:
                    editor.setObjectName(opts[0])
                    row.addWidget(editor)
                    self._plugins.append((opts[0], opts[1], plugin, editor))

            row.addStretch(1)
            vlayout.addLayout(row)

        self.setUpdatesEnabled(True)
        self.adjustSize()