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
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)
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 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)
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 __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 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 __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 __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 __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 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)
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)
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)
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()
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)
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)
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)
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 )
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 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
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)
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)
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()