def paint(self, painter, option, index): QStyledItemDelegate.paint(self, painter, option, index) text, positions = index.data(Qt.UserRole) self.initStyleOption(option, index) painter.save() painter.setFont(option.font) p = option.palette c = p.HighlightedText if option.state & QStyle.State_Selected else p.Text group = (p.Active if option.state & QStyle.State_Active else p.Inactive) c = p.color(group, c) painter.setClipRect(option.rect) if positions is None or -1 in positions: painter.setPen(c) painter.drawText(option.rect, Qt.AlignLeft | Qt.AlignVCenter | Qt.TextSingleLine, text) else: to = QTextOption() to.setWrapMode(to.NoWrap) to.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) positions = sorted(set(positions) - {-1}, reverse=True) text = '<body>%s</body>' % make_highlighted_text(Results.EMPH, text, positions) doc = QTextDocument() c = 'rgb(%d, %d, %d)'%c.getRgb()[:3] doc.setDefaultStyleSheet(' body { color: %s }'%c) doc.setHtml(text) doc.setDefaultFont(option.font) doc.setDocumentMargin(0.0) doc.setDefaultTextOption(to) height = doc.size().height() painter.translate(option.rect.left(), option.rect.top() + (max(0, option.rect.height() - height) // 2)) doc.drawContents(painter) painter.restore()
def __init__(self, *args): QPlainTextEdit.__init__(self, *args) # Default options to RightToleft options = QTextOption() options = self.document().defaultTextOption() options.setAlignment(Qt.AlignRight) options.setTextDirection(Qt.RightToLeft) self.document().setDefaultTextOption(options) # Default dictionary based on the current locale. self.dict = myspeller() # self.highlighter = Highlighter(self.document()) # self.highlighter.setDict(self.dict) self.pretxt = ''
def viewItemDrawText(self, painter, option, rect, text, color, searchText=''): # noqa C901 ''' @note: most of codes taken from QCommonStylePrivate::viewItemDrawText added highlighting and simplified for single-line textlayouts @param painter QPainter @param option QStyleOptionViewItem @param rect QRect @param text QString @param color QColor @param searchText QString @return: int ''' if not text: return 0 fontMetrics = QFontMetrics(painter.font()) elidedText = fontMetrics.elidedText(text, option.textElideMode, rect.width()) textOption = QTextOption() textOption.setWrapMode(QTextOption.NoWrap) textOption.setAlignment(QStyle.visualAlignment(textOption.textDirection(), option.displayAlignment)) textLayout = QTextLayout() textLayout.setFont(painter.font()) textLayout.setText(elidedText) textLayout.setTextOption(textOption) if searchText: # QList<int> delimiters = [] searchStrings = [ item.strip() for item in searchText.split(' ') ] searchStrings = [ item for item in searchStrings if item ] # Look for longer parts first searchStrings.sort(key=lambda x: len(x), reverse=True) text0 = text.lower() for string in searchStrings: string0 = string.lower() delimiter = text0.find(string0) while delimiter != -1: start = delimiter end = delimiter + len(string) alreadyContains = False for idx in range(0, len(delimiters), 2): dStart = delimiters[idx] dEnd = delimiters[idx+1] if dStart <= start and dEnd >= end: alreadyContains = True break if not alreadyContains: delimiters.append(start) delimiters.append(end) delimiter = text0.find(string0, end) # We need to sort delimiters to properly paint all parts that user typed delimiters.sort() # If we don't find any match, just paint it withoutany highlight if delimiters and len(delimiters) % 2 == 0: highlightParts = [] # QList<QTextLayout::FormatRange> while delimiters: highlightedPart = QTextLayout.FormatRange() start = delimiters.pop(0) end = delimiters.pop(0) highlightedPart.start = start highlightedPart.length = end - start highlightedPart.format.setFontWeight(QFont.Bold) highlightedPart.format.setUnderlineStyle(QTextCharFormat.SingleUnderline) highlightParts.append(highlightedPart) textLayout.setAdditionalFormats(highlightParts) # do layout self._s_viewItemDrawText(textLayout, rect.width()) if textLayout.lineCount() <= 0: return 0 textLine = textLayout.lineAt(0) # if elidedText after highlighting is longer than available width then # re-elide it and redo layout diff = textLine.naturalTextWidth() - rect.width() if diff > 0: # TODO: ? elidedText = fontMetrics.elidedText(elidedText, option.textElideMode, rect.width() - diff) textLayout.setText(elidedText) # redo layout self._s_viewItemDrawText(textLayout, rect.width()) if textLayout.lineCount() <= 0: return 0 textLine = textLayout.lineAt(0) # draw line painter.setPen(color) # qreal width = max(rect.width(), textLayout.lineAt(0).width()) # QRect layoutRect = QStyle.alignedRect(option.direction, option.displayAlignment, QSize(int(width), int(textLine.height())), rect) # QPointF position = layoutRect.topLeft() textLine.draw(painter, position) return int(min(rect.width(), textLayout.lineAt(0).naturalTextWidth()))