def sizeHint(self, option, index): text = index.model().data(index).toString() document = QTextDocument() document.setDefaultFont(option.font) document.setHtml(text) return QSize(document.idealWidth() + 5, option.fontMetrics.height())
def sizeHint(self, option, index): options = QStyleOptionViewItemV4(option) self.initStyleOption(options, index) doc = QTextDocument() doc.setHtml(options.text) doc.setTextWidth(options.rect.width()) return QtCore.QSize(doc.idealWidth(), doc.size().height())
def sizeHint(self, option, index): options = QStyleOptionViewItemV4(option) self.initStyleOption(options,index) doc = QTextDocument() doc.setHtml(options.text) doc.setTextWidth(options.rect.width()) return QtCore.QSize(doc.idealWidth(), doc.size().height())
def sizeHint(self, option, index): """Calculate the needed size.""" options = QStyleOptionViewItemV4(option) self.initStyleOption(options, index) doc = QTextDocument() doc.setHtml(options.text) doc.setTextWidth(options.rect.width()) return QSize(doc.idealWidth(), doc.size().height())
def sizeHint(self, option, index): optionV4 = QStyleOptionViewItemV4(option) self.initStyleOption(optionV4, index) doc = QTextDocument() doc.setHtml(optionV4.text) doc.setTextWidth(optionV4.rect.width()) return QSize(doc.idealWidth(), max(doc.size().height(), optionV4.decorationSize.height()))
def sizeHint(self, option, index): fm = option.fontMetrics if index.column() in (SRC_ADDR, DST_ADDR): text = index.model().data(index).toString() document = QTextDocument() document.setDefaultFont(option.font) document.setHtml(text) #document.setPageSize(option.rect.size()) return QSize(document.idealWidth() + 5, 1.3 * fm.height()) return QItemDelegate.sizeHint(self, option, index)
def sizeHint(self, option, index): """QStyledItemDelegate.sizeHint implementation """ options = QStyleOptionViewItemV4(option) self.initStyleOption(options, index) doc = QTextDocument() doc.setDocumentMargin(1) # bad long (multiline) strings processing doc.setTextWidth(options.rect.width()) doc.setHtml(options.text) return QSize(doc.idealWidth(), doc.size().height())
def sizeHint(self, option, index): fm = option.fontMetrics if index.column() == TEU: return QSize(fm.width("9,999,999"), fm.height()) if index.column() == DESCRIPTION: text = index.model().data(index).toString() document = QTextDocument() document.setDefaultFont(option.font) document.setHtml(text) return QSize(document.idealWidth() + 5, fm.height()) return QStyledItemDelegate.sizeHint(self, option, index)
def sizeHint(self, option, index): """QStyledItemDelegate.sizeHint implementation """ options = QStyleOptionViewItemV4(option) self.initStyleOption(options,index) doc = QTextDocument() doc.setDocumentMargin(1) # bad long (multiline) strings processing doc.setTextWidth(options.rect.width()) doc.setHtml(options.text) return QSize(doc.idealWidth(), doc.size().height())
def sizeHint( self, option, index ): fm = option.fontMetrics if index.column() in ( NOMBRE, TELEFONO, RUC, EMAIL ): text = index.model().data( index ).toString() document = QTextDocument() document.setDefaultFont( option.font ) document.setHtml( text ) return QSize( document.idealWidth() + 5, fm.height() ) elif index.column() == ACTIVO: return QSize( fm.width( "9" ), fm.height() ) else: return QStyledItemDelegate.sizeHint( self, option, index )
def sizeHint(self, option, index): """ Reimplements the :meth:`QStyledItemDelegate.sizeHint` method. """ document = QTextDocument() document.setDefaultFont(option.font) data = index.model().data(index) text = umbra.ui.common.getQVariantAsString(data) self.__label.setText(text) document.setHtml(text) return QSize(document.idealWidth() + self.__indent, option.fontMetrics.height())
def sizeHint(self, option, index): """ This method is re-implemented because Description column is using HTML, it must return the exactly number of characters for presentation purpose rather than the number of HTML raw characters. """ fm = option.fontMetrics if index.column() == TEU: return QSize(fm.width("9,999,999"), fm.height()) if index.column() == DESCRIPTION: text = index.model().data(index).toString() document = QTextDocument() document.setDefaultFont(option.font) document.setHtml(text) return QSize(document.idealWidth() + 5, fm.height()) return QStyledItemDelegate.sizeHint(self, option, index)
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))
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))
def paint(self, painter, option, index): painter.save() cell_width = self.size.width() #if option.state & QStyle.State_Selected: # painter.fillRect(option.rect, option.palette.highlight()) #painter.drawRect(option.rect) # Draw marks before translating painter # ===================================== # Draw avatar if not self.avatar: avatar_filepath = index.data(self.AvatarRole).toPyObject() self.avatar = QPixmap(avatar_filepath) x = option.rect.left() + (self.BOX_MARGIN * 2) y = option.rect.top() + (self.BOX_MARGIN * 2) rect = QRect(x, y, self.AVATAR_SIZE, self.AVATAR_SIZE) painter.drawPixmap(rect, self.avatar) # Draw verified account icon if index.data(self.VerifiedRole).toPyObject(): rect2 = QRect(rect.right() - 11, rect.bottom() - 10, 16, 16) painter.drawPixmap(rect2, self.verified_icon) marks_margin = 0 # Favorite mark if index.data(self.FavoritedRole).toPyObject(): x = cell_width - 16 - self.BOX_MARGIN y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.favorite_icon) marks_margin = 16 # Draw reposted icon if index.data(self.RepeatedRole).toPyObject(): x = cell_width - 16 - self.BOX_MARGIN - marks_margin y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.repeated_icon) # Draw protected account icon protected_icon_margin = 0 if index.data(self.ProtectedRole).toPyObject(): x = option.rect.left() + self.BOX_MARGIN + self.AVATAR_SIZE + self.LEFT_MESSAGE_MARGIN y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.protected_icon) protected_icon_margin = 16 # ==== End of pixmap drawing ==== accumulated_height = 0 # Draw fullname fullname = self.__render_fullname(cell_width, index) x = option.rect.left() + self.BOX_MARGIN + self.AVATAR_SIZE x += self.LEFT_MESSAGE_MARGIN + protected_icon_margin y = option.rect.top() painter.translate(x, y) fullname.drawContents(painter) # Draw username username = self.__render_username(cell_width, index) painter.translate(fullname.idealWidth(), 0) username.drawContents(painter) # Draw status message x = -fullname.idealWidth() - protected_icon_margin y = fullname.size().height() + self.TOP_MESSAGE_MARGIN painter.translate(x, y) message = self.__render_status_message(cell_width, index) message.drawContents(painter) accumulated_height += y + message.size().height() # Draw reposted by x = self.BOX_MARGIN + 16 - (self.LEFT_MESSAGE_MARGIN + self.AVATAR_SIZE) y = message.size().height() + self.BOTTOM_MESSAGE_MARGIN if accumulated_height < self.AVATAR_SIZE: y += (self.AVATAR_SIZE - accumulated_height) + self.COMPLEMENT_HEIGHT painter.translate(x, y) reposted_by = index.data(self.RepostedRole).toPyObject() if reposted_by: reposted = QTextDocument() reposted.setHtml("<span style='color: #999;'>%s</span>" % reposted_by) reposted.setDefaultFont(FOOTER_FONT) reposted.setTextWidth(self.__calculate_text_width(cell_width)) reposted.drawContents(painter) # Draw reposted icon rect2 = QRect(-16, 3, 16, 16) painter.drawPixmap(rect2, self.reposted_icon) # Draw datetime datetime = index.data(self.DateRole).toPyObject() timestamp = QTextDocument() timestamp.setHtml("<span style='color: #999;'>%s</span>" % datetime) timestamp.setDefaultFont(FOOTER_FONT) timestamp.setTextWidth(self.__calculate_text_width(cell_width)) x = self.size.width() - timestamp.idealWidth() - 20 - self.BOX_MARGIN painter.translate(x, 0) timestamp.drawContents(painter) painter.resetTransform() painter.translate(0, option.rect.bottom()) line = QLine(0, 0, option.rect.width(), 0) painter.setPen(QColor(230, 230, 230)) painter.drawLine(line) painter.restore()
def paint(self, painter, option, index): painter.save() cell_width = self.size.width() #if option.state & QStyle.State_Selected: # painter.fillRect(option.rect, option.palette.highlight()) #painter.drawRect(option.rect) # Draw marks before translating painter # ===================================== # Draw avatar if not self.avatar: avatar_filepath = index.data(self.AvatarRole).toPyObject() self.avatar = QPixmap(avatar_filepath) x = option.rect.left() + (self.BOX_MARGIN * 2) y = option.rect.top() + (self.BOX_MARGIN * 2) rect = QRect(x, y, self.AVATAR_SIZE, self.AVATAR_SIZE) painter.drawPixmap(rect, self.avatar) # Draw verified account icon if index.data(self.VerifiedRole).toPyObject(): rect2 = QRect(rect.right() - 11, rect.bottom() - 10, 16, 16) painter.drawPixmap(rect2, self.verified_icon) marks_margin = 0 # Favorite mark if index.data(self.FavoritedRole).toPyObject(): x = cell_width - 16 - self.BOX_MARGIN y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.favorite_icon) marks_margin = 16 # Draw reposted icon if index.data(self.RepeatedRole).toPyObject(): x = cell_width - 16 - self.BOX_MARGIN - marks_margin y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.repeated_icon) # Draw protected account icon protected_icon_margin = 0 if index.data(self.ProtectedRole).toPyObject(): x = option.rect.left( ) + self.BOX_MARGIN + self.AVATAR_SIZE + self.LEFT_MESSAGE_MARGIN y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.protected_icon) protected_icon_margin = 16 # ==== End of pixmap drawing ==== accumulated_height = 0 # Draw fullname fullname = self.__render_fullname(cell_width, index) x = option.rect.left() + self.BOX_MARGIN + self.AVATAR_SIZE x += self.LEFT_MESSAGE_MARGIN + protected_icon_margin y = option.rect.top() painter.translate(x, y) fullname.drawContents(painter) # Draw username username = self.__render_username(cell_width, index) painter.translate(fullname.idealWidth(), 0) username.drawContents(painter) # Draw status message x = -fullname.idealWidth() - protected_icon_margin y = fullname.size().height() + self.TOP_MESSAGE_MARGIN painter.translate(x, y) message = self.__render_status_message(cell_width, index) message.drawContents(painter) accumulated_height += y + message.size().height() # Draw reposted by x = self.BOX_MARGIN + 16 - (self.LEFT_MESSAGE_MARGIN + self.AVATAR_SIZE) y = message.size().height() + self.BOTTOM_MESSAGE_MARGIN if accumulated_height < self.AVATAR_SIZE: y += (self.AVATAR_SIZE - accumulated_height) + self.COMPLEMENT_HEIGHT painter.translate(x, y) reposted_by = index.data(self.RepostedRole).toPyObject() if reposted_by: reposted = QTextDocument() reposted.setHtml("<span style='color: #999;'>%s</span>" % reposted_by) reposted.setDefaultFont(FOOTER_FONT) reposted.setTextWidth(self.__calculate_text_width(cell_width)) reposted.drawContents(painter) # Draw reposted icon rect2 = QRect(-16, 3, 16, 16) painter.drawPixmap(rect2, self.reposted_icon) # Draw datetime datetime = index.data(self.DateRole).toPyObject() timestamp = QTextDocument() timestamp.setHtml("<span style='color: #999;'>%s</span>" % datetime) timestamp.setDefaultFont(FOOTER_FONT) timestamp.setTextWidth(self.__calculate_text_width(cell_width)) x = self.size.width() - timestamp.idealWidth() - 20 - self.BOX_MARGIN painter.translate(x, 0) timestamp.drawContents(painter) painter.resetTransform() painter.translate(0, option.rect.bottom()) line = QLine(0, 0, option.rect.width(), 0) painter.setPen(QColor(230, 230, 230)) painter.drawLine(line) painter.restore()