class XRolloutItem(QWidget): def __init__( self, rolloutWidget, widget, title = 'Rollout', expanded = False ): super(XRolloutItem, self).__init__(rolloutWidget) # initialize the interface self._rolloutWidget = rolloutWidget self._widget = widget self._expanded = expanded self._titleButton = QPushButton(self) self._titleButton.setFlat(True) self._titleButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) self._titleButton.setFixedHeight(20) self._titleButton.setText(title) self._titleButton.setStyleSheet(TITLE_STYLESHEET) layout = QVBoxLayout() layout.setContentsMargins(6, 6, 6, 9) layout.setSpacing(2) layout.addWidget(self._titleButton) layout.addWidget(widget) self.setLayout(layout) # initialize the expanded state self.setExpanded(expanded) # create connections self._titleButton.clicked.connect( self.toggleExpanded ) def collapse( self ): """ Collapses this rollout item. """ self.setExpanded(False) def expand( self ): """ Expands this rollout item. """ self.setExpanded(True) def isCollapsed( self ): """ Returns whether or not this rollout is in the collapsed state. :return <bool> """ return not self._expanded def paintEvent( self, event ): """ Overloads the paint event to draw rounded edges on this widget. :param event | <QPaintEvent> """ super(XRolloutItem, self).paintEvent(event) with XPainter(self) as painter: w = self.width() - 3 h = self.height() - 3 color = self.palette().color(QPalette.Midlight) color = color.darker(180) pen = QPen(color) pen.setWidthF(0.5) painter.setPen(pen) painter.setBrush(self.palette().color(QPalette.Midlight)) painter.setRenderHint(XPainter.Antialiasing) painter.drawRoundedRect(1, 1, w, h, 10, 10) def isExpanded( self ): """ Returns whether or not this rollout is in the expanded state. :return <bool> """ return self._expanded def rolloutWidget( self ): """ Returns the rollout widget that this item is associated with. :return <XRolloutWidget> """ return self._rolloutWidget def setCollapsed( self, state ): """ Sets whether or not this rollout is in the collapsed state. :param state | <bool> """ return self.setExpanded(not state) def setExpanded( self, state ): """ Sets whether or not this rollout is in the expanded state. :param state | <bool> """ self._expanded = state self._widget.setVisible(state) if ( state ): ico = projexui.resources.find('img/treeview/triangle_down.png') else: ico = projexui.resources.find('img/treeview/triangle_right.png') self._titleButton.setIcon(QIcon(ico)) # emit the signals for this widget rollout = self.rolloutWidget() if ( not rollout.signalsBlocked() ): index = rollout.widget().layout().indexOf(self) rollout.itemCollapsed.emit(index) rollout.itemExpanded.emit(index) def setTitle( self, title ): """ Sets the title for this item to the inputed title text. :param title | <str> """ self._titleLabel.setText(title) def title( self ): """ Returns the title for this rollout. :return <str> """ return nativestring(self._titleLabel.text()) def toggleExpanded( self ): """ Toggles whether or not this rollout is in the expanded state. """ self.setExpanded(not self.isExpanded()) def widget( self ): """ Returns the widget that is associated with this rollout item. :return <QWidget> """ return self._widget
class XRolloutItem(QWidget): def __init__(self, rolloutWidget, widget, title='Rollout', expanded=False): super(XRolloutItem, self).__init__(rolloutWidget) # initialize the interface self._rolloutWidget = rolloutWidget self._widget = widget self._expanded = expanded self._titleButton = QPushButton(self) self._titleButton.setFlat(True) self._titleButton.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) self._titleButton.setFixedHeight(20) self._titleButton.setText(title) self._titleButton.setStyleSheet(TITLE_STYLESHEET) layout = QVBoxLayout() layout.setContentsMargins(6, 6, 6, 9) layout.setSpacing(2) layout.addWidget(self._titleButton) layout.addWidget(widget) self.setLayout(layout) # initialize the expanded state self.setExpanded(expanded) # create connections self._titleButton.clicked.connect(self.toggleExpanded) def collapse(self): """ Collapses this rollout item. """ self.setExpanded(False) def expand(self): """ Expands this rollout item. """ self.setExpanded(True) def isCollapsed(self): """ Returns whether or not this rollout is in the collapsed state. :return <bool> """ return not self._expanded def paintEvent(self, event): """ Overloads the paint event to draw rounded edges on this widget. :param event | <QPaintEvent> """ super(XRolloutItem, self).paintEvent(event) with XPainter(self) as painter: w = self.width() - 3 h = self.height() - 3 color = self.palette().color(QPalette.Midlight) color = color.darker(180) pen = QPen(color) pen.setWidthF(0.5) painter.setPen(pen) painter.setBrush(self.palette().color(QPalette.Midlight)) painter.setRenderHint(XPainter.Antialiasing) painter.drawRoundedRect(1, 1, w, h, 10, 10) def isExpanded(self): """ Returns whether or not this rollout is in the expanded state. :return <bool> """ return self._expanded def rolloutWidget(self): """ Returns the rollout widget that this item is associated with. :return <XRolloutWidget> """ return self._rolloutWidget def setCollapsed(self, state): """ Sets whether or not this rollout is in the collapsed state. :param state | <bool> """ return self.setExpanded(not state) def setExpanded(self, state): """ Sets whether or not this rollout is in the expanded state. :param state | <bool> """ self._expanded = state self._widget.setVisible(state) if (state): ico = projexui.resources.find('img/treeview/triangle_down.png') else: ico = projexui.resources.find('img/treeview/triangle_right.png') self._titleButton.setIcon(QIcon(ico)) # emit the signals for this widget rollout = self.rolloutWidget() if (not rollout.signalsBlocked()): index = rollout.widget().layout().indexOf(self) rollout.itemCollapsed.emit(index) rollout.itemExpanded.emit(index) def setTitle(self, title): """ Sets the title for this item to the inputed title text. :param title | <str> """ self._titleLabel.setText(title) def title(self): """ Returns the title for this rollout. :return <str> """ return nativestring(self._titleLabel.text()) def toggleExpanded(self): """ Toggles whether or not this rollout is in the expanded state. """ self.setExpanded(not self.isExpanded()) def widget(self): """ Returns the widget that is associated with this rollout item. :return <QWidget> """ return self._widget
class XCommentEdit(XTextEdit): attachmentRequested = Signal() def __init__(self, parent=None): super(XCommentEdit, self).__init__(parent) # define custom properties self._attachments = {} self._showAttachments = True # create toolbar self._toolbar = QToolBar(self) self._toolbar.setMovable(False) self._toolbar.setFixedHeight(30) self._toolbar.setAutoFillBackground(True) self._toolbar.setFocusProxy(self) self._toolbar.hide() # create toolbar buttons self._attachButton = QToolButton(self) self._attachButton.setIcon(QIcon(resources.find('img/attach.png'))) self._attachButton.setToolTip('Add Attachment') self._attachButton.setAutoRaise(True) self._attachButton.setIconSize(QSize(24, 24)) self._attachButton.setFixedSize(26, 26) self._submitButton = QPushButton(self) self._submitButton.setText('Submit') self._submitButton.setFocusProxy(self) # create attachments widget self._attachmentsEdit = XMultiTagEdit(self) self._attachmentsEdit.setAutoResizeToContents(True) self._attachmentsEdit.setFrameShape(XMultiTagEdit.NoFrame) self._attachmentsEdit.setViewMode(XMultiTagEdit.ListMode) self._attachmentsEdit.setEditable(False) self._attachmentsEdit.setFocusProxy(self) self._attachmentsEdit.hide() # define toolbar layout spacer = QWidget(self) spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self._attachAction = self._toolbar.addWidget(self._attachButton) self._toolbar.addWidget(spacer) self._toolbar.addWidget(self._submitButton) # set standard properties self.setAutoResizeToContents(True) self.setHint('add comment') self.setFocusPolicy(Qt.StrongFocus) self.setRequireShiftForNewLine(True) # create connections self._attachButton.clicked.connect(self.attachmentRequested) self._submitButton.clicked.connect(self.acceptText) self._attachmentsEdit.tagRemoved.connect(self.removeAttachment) self.focusChanged.connect(self.setToolbarVisible) def addAttachment(self, title, attachment): """ Adds an attachment to this comment. :param title | <str> attachment | <variant> """ self._attachments[title] = attachment self.resizeToContents() def attachments(self): """ Returns a list of attachments that have been linked to this widget. :return {<str> title: <variant> attachment, ..} """ return self._attachments.copy() def attachButton(self): """ Returns the attach button from the toolbar for this widget. :return <QToolButton> """ return self._attachButton @Slot() def clear(self): """ Clears out this widget and its attachments. """ # clear the attachment list self._attachments.clear() super(XCommentEdit, self).clear() def isToolbarVisible(self): """ Returns whether or not the toolbar for this comment edit is currently visible to the user. :return <bool> """ return self._toolbar.isVisible() def keyPressEvent(self, event): if event.key() == Qt.Key_Escape: self.clear() event.accept() else: super(XCommentEdit, self).keyPressEvent(event) @Slot() def pickAttachment(self): """ Prompts the user to select an attachment to add to this edit. """ filename = QFileDialog.getOpenFileName(self.window(), 'Select Attachment', '', 'All Files (*.*)') if type(filename) == tuple: filename = nativestring(filename[0]) filename = nativestring(filename) if filename: self.addAttachment(os.path.basename(filename), filename) def removeAttachment(self, title): """ Removes the attachment from the given title. :param title | <str> :return <variant> | attachment """ attachment = self._attachments.pop(nativestring(title), None) if attachment: self.resizeToContents() return attachment def resizeEvent(self, event): super(XCommentEdit, self).resizeEvent(event) self._toolbar.resize(self.width() - 4, 30) edit = self._attachmentsEdit edit.resize(self.width() - 4, edit.height()) def resizeToContents(self): """ Resizes this toolbar based on the contents of its text. """ if self._toolbar.isVisible(): doc = self.document() h = doc.documentLayout().documentSize().height() offset = 34 # update the attachments edit edit = self._attachmentsEdit if self._attachments: edit.move(2, self.height() - edit.height() - 31) edit.setTags(sorted(self._attachments.keys())) edit.show() offset = 34 + edit.height() else: edit.hide() offset = 34 self.setFixedHeight(h + offset) self._toolbar.move(2, self.height() - 32) else: super(XCommentEdit, self).resizeToContents() def setAttachments(self, attachments): """ Sets the attachments for this widget to the inputed list of attachments. :param attachments | {<str> title: <variant> attachment, ..} """ self._attachments = attachments self.resizeToContents() def setSubmitText(self, text): """ Sets the submission text for this edit. :param text | <str> """ self._submitButton.setText(text) def setShowAttachments(self, state): """ Sets whether or not to show the attachments for this edit. :param state | <bool> """ self._showAttachments = state self._attachAction.setVisible(state) def setToolbarVisible(self, state): """ Sets whether or not the toolbar is visible. :param state | <bool> """ self._toolbar.setVisible(state) self.resizeToContents() def showAttachments(self): """ Returns whether or not to show the attachments for this edit. :return <bool> """ return self._showAttachments def submitButton(self): """ Returns the submit button for this edit. :return <QPushButton> """ return self._submitButton def submitText(self): """ Returns the submission text for this edit. :return <str> """ return self._submitButton.text() def toolbar(self): """ Returns the toolbar widget for this comment edit. :return <QToolBar> """ return self._toolbar x_showAttachments = Property(bool, showAttachments, setShowAttachments) x_submitText = Property(str, submitText, setSubmitText)