def paint(self, painter, option, index): optionV4 = QStyleOptionViewItemV4(option) self.initStyleOption(optionV4, index) style = optionV4.widget.style() if optionV4.widget else QApplication.style() doc = QTextDocument() doc.setHtml(optionV4.text) # painting item without text optionV4.text = QString() style.drawControl(QStyle.CE_ItemViewItem, optionV4, painter) ctx = QAbstractTextDocumentLayout.PaintContext() # Hilight text if item is selected if optionV4.state & QStyle.State_Selected: ctx.palette.setColor(QPalette.Text, optionV4.palette.color(QPalette.Active, QPalette.HighlightedText)) textRect = style.subElementRect(QStyle.SE_ItemViewItemText, optionV4) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def paint(self, painter, option, index): optionV4 = QStyleOptionViewItemV4(option) self.initStyleOption(optionV4, index) style = optionV4.widget.style() if optionV4.widget else QApplication.style() doc = QTextDocument() doc.setHtml(optionV4.text) # painting item without text optionV4.text = QString() style.drawControl(QStyle.CE_ItemViewItem, optionV4, painter) ctx = QAbstractTextDocumentLayout.PaintContext() # Hilight text if item is selected if optionV4.state & QStyle.State_Selected: ctx.palette.setColor(QPalette.Text, optionV4.palette.color(QPalette.Active, QPalette.HighlightedText)) textRect = style.subElementRect(QStyle.SE_ItemViewItemText, optionV4) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def paint(self, painter, option, index): """QStyledItemDelegate.paint implementation """ option.state &= ~QStyle.State_HasFocus # never draw focus rect options = QStyleOptionViewItemV4(option) self.initStyleOption(options, index) style = QApplication.style( ) if options.widget is None else options.widget.style() doc = QTextDocument() doc.setDocumentMargin(1) doc.setHtml(options.text) # bad long (multiline) strings processing doc.setTextWidth(options.rect.width()) options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() # Highlighting text if item is selected if option.state & QStyle.State_Selected: ctx.palette.setColor( QPalette.Text, option.palette.color(QPalette.Active, QPalette.HighlightedText)) textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def paint(self, painter, option, index): """Render the delegate for the item.""" if index.column() != self._html_column: return QStyledItemDelegate.paint(self, painter, option, index) options = QStyleOptionViewItemV4(option) self.initStyleOption(options, index) if options.widget is None: style = QApplication.style() else: style = options.widget.style() doc = QTextDocument() doc.setHtml(options.text) options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def paint(self, painter, option, index): """QStyledItemDelegate.paint implementation """ option.state &= ~QStyle.State_HasFocus # never draw focus rect options = QStyleOptionViewItemV4(option) self.initStyleOption(options, index) style = QApplication.style() if options.widget is None else options.widget.style() doc = QTextDocument() doc.setDocumentMargin(1) doc.setHtml(options.text) # bad long (multiline) strings processing doc.setTextWidth(options.rect.width()) options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() # Highlighting text if item is selected if option.state & QStyle.State_Selected: ctx.palette.setColor(QPalette.Text, option.palette.color(QPalette.Active, QPalette.HighlightedText)) textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def paint(self, painter, option, index): """Render the delegate for the item.""" if index.column() != self._html_column: return QStyledItemDelegate.paint(self, painter, option, index) options = QStyleOptionViewItemV4(option) self.initStyleOption(options, index) if options.widget is None: style = QApplication.style() else: style = options.widget.style() doc = QTextDocument() doc.setHtml(options.text) options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def paint(self, painter, option, index): options = QStyleOptionViewItemV4(option) self.initStyleOption(options, index) style = QApplication.style( ) if options.widget is None else options.widget.style() doc = QTextDocument() doc.setHtml(options.text) options.text = "" style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) # Highlighting text if item is selected if options.state & QStyle.State_Selected: # ctx.palette.setColor( # QPalette.Text, options.palette.color(QPalette.Active, QPalette.HighlightedText) # ) # painter.setBrush( options.palette.color( QPalette.Active, QPalette.Highlight ) ) # painter.setBrush( QColor( '#c1f48b' ) ) painter.setBrush(QColor(0, 180, 0, 30)) painter.setPen(Qt.NoPen) painter.drawRect(textRect) elif options.state & QStyle.State_MouseOver: # painter.setBrush( QColor( '#faffb8' ) ) # painter.setPen( Qt.NoPen ) # painter.drawRect( textRect ) painter.setBrush(QColor(0, 255, 0, 10)) painter.setPen(Qt.NoPen) painter.drawRect(textRect) else: painter.setPen(QColor(0, 0, 0, 10)) painter.drawLine(textRect.bottomLeft(), textRect.bottomRight()) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def paint(self, painter, option, index): options = QStyleOptionViewItemV4(option) self.initStyleOption(options,index) style = QApplication.style() if options.widget is None else options.widget.style() doc = QTextDocument() doc.setHtml(options.text) options.text = "" style.drawControl( QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() textRect = style.subElementRect( QStyle.SE_ItemViewItemText, options ) # Highlighting text if item is selected if options.state & QStyle.State_Selected : # ctx.palette.setColor( # QPalette.Text, options.palette.color(QPalette.Active, QPalette.HighlightedText) # ) # painter.setBrush( options.palette.color( QPalette.Active, QPalette.Highlight ) ) # painter.setBrush( QColor( '#c1f48b' ) ) painter.setBrush( QColor( 0,180,0,30 ) ) painter.setPen( Qt.NoPen ) painter.drawRect( textRect ) elif options.state & QStyle.State_MouseOver : # painter.setBrush( QColor( '#faffb8' ) ) # painter.setPen( Qt.NoPen ) # painter.drawRect( textRect ) painter.setBrush( QColor( 0,255,0,10 ) ) painter.setPen( Qt.NoPen ) painter.drawRect( textRect ) else: painter.setPen( QColor( 0,0,0,10 ) ) painter.drawLine( textRect.bottomLeft(), textRect.bottomRight() ) painter.save() painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def renderLabel(self, painter): """Render the current timestamp on the map canvas""" if not self.showLabel or not self.model.hasLayers() or not self.dock.pushButtonToggleTime.isChecked(): return dt = self.model.getCurrentTimePosition() if dt is None: return labelString = self.labelOptions.getLabel(dt) # Determine placement of label given cardinal directions flags = 0 for direction, flag in ('N', Qt.AlignTop), ('S', Qt.AlignBottom), ('E', Qt.AlignRight), ('W', Qt.AlignLeft): if direction in self.labelOptions.placement: flags |= flag # Get canvas dimensions width = painter.device().width() height = painter.device().height() painter.setRenderHint(painter.Antialiasing, True) txt = QTextDocument() html = """<span style="background-color:%s; padding: 5px; font-size: %spx;"> <font face="%s" color="%s">%s</font> </span> """\ % (self.labelOptions.bgcolor, self.labelOptions.size, self.labelOptions.font, self.labelOptions.color, labelString) txt.setHtml(html) layout = txt.documentLayout() size = layout.documentSize() if flags & Qt.AlignRight: x = width - 5 - size.width() elif flags & Qt.AlignLeft: x = 5 else: x = width / 2 - size.width() / 2 if flags & Qt.AlignBottom: y = height - 5 - size.height() elif flags & Qt.AlignTop: y = 5 else: y = height / 2 - size.height() / 2 painter.translate(x, y) layout.draw(painter, QAbstractTextDocumentLayout.PaintContext()) painter.translate(-x, -y) # translate back
class MessageItemDelegate(QStyledItemDelegate): def __init__(self, parentView, logger, column=None, margin=50): super(MessageItemDelegate, self).__init__(parentView) self.logger = logger # We need that to receive mouse move events in editorEvent parentView.setMouseTracking(True) # Revert the mouse cursor when the mouse isn't over # an item but still on the view widget parentView.viewportEntered.connect(self.unsetParentCursor) self.document = QTextDocument() self.mouseOverDocument = self.document self.mouseOverDocumentRow = -1 self.mouseOverOption = None self.lastTextPos = QPoint(0, 0) self._editIndex = None self._editor = None self._column = column self._margin = margin ownGradient = QLinearGradient(0, 0, 0, 10) ownGradient.setColorAt(0, QColor(229, 239, 254)) ownGradient.setColorAt(1, QColor(182, 208, 251)) self._ownBrush = QBrush(ownGradient) self._ownPenColor = QColor(104, 126, 164) otherGradient = QLinearGradient(0, 0, 0, 10) otherGradient.setColorAt(0, QColor(248, 248, 248)) otherGradient.setColorAt(1, QColor(200, 200, 200)) self._otherBrush = QBrush(otherGradient) self._otherPenColor = QColor(153, 153, 153) self._timeFont = QFont("default", 12, QFont.Bold) self.closeEditor.connect(self.editorClosing) self._rowHeights = {} @loggingSlot() def unsetParentCursor(self): self.parent().unsetCursor() def setEditIndex(self, modelIndex): self._editIndex = modelIndex def getEditIndex(self): return self._editIndex @loggingSlot(QWidget, QAbstractItemDelegate.EndEditHint) def editorClosing(self, _editor, _hint): self._editor = None self.setEditIndex(None) def getEditor(self): return self._editor def createEditor(self, parent, option_, modelIndex): self.setEditIndex(modelIndex) option = QStyleOptionViewItemV4(option_) self.initStyleOption(option, modelIndex) text = QString(option.text) editorWidget = EditorWidget(parent) editor = ItemEditor(text, self._preferredMessageWidth(option.rect.width()), editorWidget) editorWidget.setItemEditor(editor) messageRect = self._getMessageRect(option, editor.document(), modelIndex, relativeToItem=True) pos = messageRect.topLeft() editor.move(pos) editor.resize(messageRect.size()) self._editor = editorWidget return editorWidget def setModelData(self, *_args, **_kwargs): pass def _preferredMessageWidth(self, textRectWidth): return textRectWidth - self._margin def _getMessageRect(self, option, doc, modelIndex, relativeToItem=False): rightAligned = modelIndex.data(ChatMessagesModel.OWN_MESSAGE_ROLE).toBool() statusIcon = modelIndex.data(ChatMessagesModel.STATUS_ICON_ROLE) hasStatusIcon = statusIcon != None and not statusIcon.isNull() textRect = option.rect documentWidth = doc.idealWidth() if rightAligned: xOffset = textRect.width() - documentWidth - 3 if hasStatusIcon: xOffset -= 20 else: xOffset = 3 if hasStatusIcon: xOffset += 20 height = doc.size().height() if modelIndex.row() not in self._rowHeights: self._rowHeights[modelIndex.row()] = height elif self._rowHeights[modelIndex.row()] != height: self._rowHeights[modelIndex.row()] = height self.sizeHintChanged.emit(modelIndex) if height < 32: # vertically center yOffset = (32. - height) / 2 + 1 else: yOffset = 0 textPos = QPoint(0,0) if relativeToItem else textRect.topLeft() textPos += QPoint(xOffset, yOffset) return QRect(textPos, QSize(documentWidth, height)) def _paintTime(self, painter, option, modelIndex): if modelIndex.column() != 1: return # total rect for us to paint in textRect = option.rect rtime, _ok = modelIndex.data(Qt.DisplayRole).toDouble() timeString = formatTime(localtime(rtime)) painter.save() painter.setRenderHint(QPainter.Antialiasing) painter.translate(textRect.topLeft()) painter.setFont(self._timeFont) textWidth = painter.fontMetrics().width(timeString) painter.drawText((textRect.size().width() - textWidth) / 2, 13, timeString) painter.restore() def paint(self, painter, option1, modelIndex): if self._column is not None and modelIndex.column() != self._column: return super(MessageItemDelegate, self).paint(painter, option1, modelIndex) option = QStyleOptionViewItemV4(option1) self.initStyleOption(option, modelIndex) if modelIndex.data(Qt.DisplayRole).type() == QMetaType.Double: # this is a time item self._paintTime(painter, option, modelIndex) return text = QString(option.text) if not text: option1.decorationAlignment = Qt.AlignLeft return super(MessageItemDelegate, self).paint(painter, option1, modelIndex) rightAligned = modelIndex.data(ChatMessagesModel.OWN_MESSAGE_ROLE).toBool() selected = (int(option.state) & int(QStyle.State_Selected)) != 0 editing = self._editIndex == modelIndex self.document.setHtml(text) self.document.setTextWidth(self._preferredMessageWidth(option.rect.width())) ctx = QAbstractTextDocumentLayout.PaintContext() # Highlighting text if item is selected if selected: ctx.palette.setColor(QPalette.Text, option.palette.color(QPalette.Active, QPalette.HighlightedText)) # total rect for us to paint in textRect = option.rect # final rect to paint message in messageRect = self._getMessageRect(option, self.document, modelIndex) painter.save() mouseOver = (int(option.state) & int(QStyle.State_MouseOver)) != 0 if mouseOver: self.mouseOverDocument = QTextDocument() self.mouseOverDocument.setHtml(text) self.mouseOverDocument.setTextWidth(self._preferredMessageWidth(option.rect.width())) self.mouseOverDocumentRow = modelIndex.row() self.lastTextPos = textRect.topLeft() self.mouseOverOption = option # draw decoration painter.translate(textRect.topLeft()) statusIcon = modelIndex.data(ChatMessagesModel.STATUS_ICON_ROLE) if statusIcon != None and not statusIcon.isNull(): statusIcon = QIcon(statusIcon) if rightAligned: statusIcon.paint(painter, textRect.size().width() - 19, 8, 16, 16, Qt.AlignCenter) else: statusIcon.paint(painter, 3, 8, 16, 16, Qt.AlignCenter) # draw message painter.restore() painter.save() painter.setRenderHint(QPainter.Antialiasing) painter.translate(messageRect.topLeft()) if not editing: painter.setBrush(self._ownBrush if rightAligned else self._otherBrush) painter.setPen(self._ownPenColor if rightAligned else self._otherPenColor) painter.drawRoundedRect(QRectF(QPointF(0, 0.5), QSizeF(self.document.idealWidth(), self.document.size().height() - 1.)), 7, 7) painter.setClipRect(textRect.translated(-textRect.topLeft())) if not editing: self.document.documentLayout().draw(painter, ctx) painter.restore() startEditing = pyqtSignal(QModelIndex) def shouldStartEditAt(self, eventPos, modelIndex): option = QStyleOptionViewItemV4() option.initFrom(self.parent()) option.rect.setHeight(32) self.initStyleOption(option, modelIndex) if modelIndex.row() != self.mouseOverDocumentRow: # TODO reset document self.logger.warning("shouldStartEditAt(): wrong mouse over document") return False messageRect = self._getMessageRect(self.mouseOverOption, self.mouseOverDocument, modelIndex) anchorPos = QPointF(eventPos) - QPointF(messageRect.topLeft()) anchor = self.mouseOverDocument.documentLayout().anchorAt(anchorPos) if anchor != "": return False return messageRect.contains(eventPos) def editorEvent(self, event, _model, option_, modelIndex): if self._column and modelIndex.column() != self._column: return False option = QStyleOptionViewItemV4(option_) self.initStyleOption(option, modelIndex) text = QString(option.text) if not text: self.parent().unsetCursor() return False if event.type() not in (QEvent.MouseMove, QEvent.MouseButtonRelease, QEvent.MouseButtonPress) \ or not (option.state & QStyle.State_Enabled): return False if modelIndex.row() != self.mouseOverDocumentRow: return False # Get the link at the mouse position pos = event.pos() messageRect = self._getMessageRect(option, self.mouseOverDocument, modelIndex) anchor = convert_string(self.mouseOverDocument.documentLayout().anchorAt(QPointF(pos) - QPointF(messageRect.topLeft()))) if anchor == "": if messageRect.contains(pos): self.parent().setCursor(Qt.IBeamCursor) else: self.parent().unsetCursor() else: self.parent().setCursor(Qt.PointingHandCursor) if event.type() == QEvent.MouseButtonRelease: if anchor.startswith(u"www."): anchor = u"http://" + anchor webbrowser.open(anchor) return True return False def sizeHint(self, option1, index): # option.rect is a zero rect width = self.parent().columnWidth(index.column()) if index.data(Qt.DisplayRole).type() == QMetaType.Double: return QSize(width, 18) option = QStyleOptionViewItemV4(option1) self.initStyleOption(option, index) if not option.text: iconSize = option.icon.actualSize(QSize(32, 32)) return QSize(32, max(32, iconSize.height() + 4)) doc = QTextDocument() doc.setHtml(option.text) doc.setTextWidth(self._preferredMessageWidth(width)) return QSize(doc.idealWidth(), max(32, doc.size().height() + 4))