def pixmap(cursor, num_lines=6, scale=0.8): """Return a QPixmap displaying the selected lines of the document. If the cursor has no selection, num_lines are drawn. By default the text is drawn 0.8 * the normal font size. You can change that by supplying the scale parameter. """ block = cursor.document().findBlock(cursor.selectionStart()) c2 = QTextCursor(block) if cursor.hasSelection(): c2.setPosition(cursor.selectionEnd(), QTextCursor.KeepAnchor) c2.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) else: c2.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor, num_lines) data = textformats.formatData('editor') doc = QTextDocument() font = QFont(data.font) font.setPointSizeF(font.pointSizeF() * scale) doc.setDefaultFont(font) doc.setPlainText(c2.selection().toPlainText()) if metainfo.info(cursor.document()).highlighting: highlighter.highlight(doc, state=tokeniter.state(block)) size = doc.size().toSize() + QSize(8, -4) pix = QPixmap(size) pix.fill(data.baseColors['background']) doc.drawContents(QPainter(pix)) return pix
def paint(self, painter, option, index): self.initStyleOption(option, index) foreground = index.data(Qt.ForegroundRole) font = index.data(Qt.FontRole) style = QApplication.style() doc = QTextDocument() if index.column() == HistoryTableModel.columns_types.index('pubkey'): doc.setHtml(option.text) else: doc.setPlainText(option.text) option.text = "" style.drawControl(QStyle.CE_ItemViewItem, option, painter) ctx = QAbstractTextDocumentLayout.PaintContext() if foreground: if foreground.isValid(): ctx.palette.setColor(QPalette.Text, foreground) if font: doc.setDefaultFont(font) text_rect = style.subElementRect(QStyle.SE_ItemViewItemText, option) painter.save() painter.translate(text_rect.topLeft()) painter.setClipRect(text_rect.translated(-text_rect.topLeft())) doc.documentLayout().draw(painter, ctx) painter.restore()
def sizeHint(self, styleOption, modelIndex): """Return the size of Data Edit Cells with rich text. Other cells return the base class size. Arguments: styleOption -- the data for styles and geometry modelIndex -- the index of the cell to be painted """ cell = self.parent().item(modelIndex.row(), modelIndex.column()) if isinstance(cell, DataEditCell): doc = cell.doc doc.setTextWidth(styleOption.rect.width()) size = doc.documentLayout().documentSize().toSize() maxHeight = self.parent().height() * 9 // 10 # 90% of view height if (size.height() > maxHeight and globalref.genOptions['EditorLimitHeight']): size.setHeight(maxHeight) if cell.field.numLines > 1: minDoc = QTextDocument('\n' * (cell.field.numLines - 1)) minDoc.setDefaultFont(cell.doc.defaultFont()) minHeight = ( minDoc.documentLayout().documentSize().toSize().height()) if minHeight > size.height(): size.setHeight(minHeight) return size + QSize(0, 4) return super().sizeHint(styleOption, modelIndex)
def paint(self, painter, option, index): text = index.model().data(index, Qt.DisplayRole) document = QTextDocument() # metrics = QFontMetrics(document.defaultFont()) metrics = painter.fontMetrics() # font = QFont() # font.setPointSize(12) document.setDefaultFont(G.entriesFont) if index.column() == 0: document.setTextWidth(69) elif index.column() == 1: document.setTextWidth(514) if option.state & QStyle.State_Selected: document.setHtml("<b bgcolor=#E6E600> <font size={} font color={}>{}" "</font></b>".format("2", G.selectionColor, text)) else: w = metrics.boundingRect('W').width() # print(w) txt = text[0:(514*4)//w] document.setHtml("<p align (center) bgcolor=white> <font size={} " "font color={}>{}" "</font></p>".format("2", "black", txt)) painter.save() painter.translate(option.rect.x(), option.rect.y()) document.drawContents(painter) painter.restore()
def pixmap(cursor, num_lines=6, scale=0.8): """Return a QPixmap displaying the selected lines of the document. If the cursor has no selection, num_lines are drawn. By default the text is drawn 0.8 * the normal font size. You can change that by supplying the scale parameter. """ block = cursor.document().findBlock(cursor.selectionStart()) c2 = QTextCursor(block) if cursor.hasSelection(): c2.setPosition(cursor.selectionEnd(), QTextCursor.KeepAnchor) c2.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) else: c2.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor, num_lines) data = textformats.formatData('editor') doc = QTextDocument() font = QFont(data.font) font.setPointSizeF(font.pointSizeF() * scale) doc.setDefaultFont(font) doc.setPlainText(c2.selection().toPlainText()) if metainfo.info(cursor.document()).highlighting: highlighter.highlight(doc, state=tokeniter.state(block)) size = doc.size().toSize() + QSize(8, -4) pix = QPixmap(size) pix.fill(data.baseColors['background']) doc.drawContents(QPainter(pix)) return pix
def textDocument(self, title, htmltext): td = QTextDocument() td.setMetaInformation(QTextDocument.DocumentTitle, title) if self.ss: td.setDefaultStyleSheet(self.ss) td.setHtml(htmltext) td.setDefaultFont(globalSettings.font) return td
def textDocument(self, title, htmltext): td = QTextDocument() td.setMetaInformation(QTextDocument.DocumentTitle, title) if self.ss: td.setDefaultStyleSheet(self.ss) td.setHtml(htmltext) td.setDefaultFont(globalSettings.font) return td
def textDocument(self): td = QTextDocument() td.setMetaInformation(QTextDocument.DocumentTitle, self.getDocumentTitle()) if self.ss: td.setDefaultStyleSheet(self.ss) td.setHtml(self.getHtml()) td.setDefaultFont(globalSettings.font) return td
def textDocument(self): td = QTextDocument() td.setMetaInformation(QTextDocument.DocumentTitle, self.getDocumentTitle()) if self.ss: td.setDefaultStyleSheet(self.ss) td.setHtml(self.getHtml()) if self.font: td.setDefaultFont(self.font) return td
def sizeHint(self, option, index): fm = option.fontMetrics if index.column() == ATOM: return QSize(fm.width("9,999,999"), fm.height()) if index.column() == resName: text = index.model().data(index) 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): fm = option.fontMetrics if index.column() == residNum: return QSize(fm.width("9,999,999"), fm.height()) if index.column() == residName: text = index.model().data(index) document = QTextDocument() document.setDefaultFont(option.font) document.setHtml(text) return QSize(document.idealWidth() + 5, fm.height()) return QStyledItemDelegate.sizeHint(self, option, index)
class DataEditCell(QTableWidgetItem): """Class override for data edit view cells. Used for the cells with editable content. """ def __init__(self, spot, field, titleCellRef, typeCellRef): """Initialize the editable cells in the data edit view. Arguments: spot -- the spot referenced by this cell field -- the field object referenced by this cell titleCellRef -- the title cell to update based on data changes typeCellRef -- the format type cell to update based on type changes """ super().__init__() self.spot = spot self.node = spot.nodeRef self.field = field self.titleCellRef = titleCellRef self.typeCellRef = typeCellRef self.errorFlag = False self.cursorPos = (-1, -1) self.scrollPos = -1 # store doc to speed up delegate sizeHint and paint calls self.doc = QTextDocument() self.doc.setDefaultFont(defaultFont) self.doc.setDocumentMargin(6) self.updateText() def updateText(self): """Update the text based on the current node data. """ self.errorFlag = False try: self.setText(self.field.editorText(self.node)) except ValueError as err: if len(err.args) >= 2: self.setText(err.args[1]) else: self.setText(self.node.data.get(self.field.name, '')) self.errorFlag = True if self.field.showRichTextInCell: self.doc.setHtml(self.text()) else: self.doc.setPlainText(self.text()) def storeEditorState(self, editor): """Store the cursor & scroll positions baseed on an editor signal. Arguments: editor -- the editor that will get its state saved """ self.cursorPos = editor.cursorPosTuple() self.scrollPos = editor.scrollPosition()
def sizeHint(self, option, index): """QStyledItemDelegate.sizeHint implementation """ options = QStyleOptionViewItem(option) self.initStyleOption(options, index) doc = QTextDocument() if self._font is not None: doc.setDefaultFont(self._font) 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): """QStyledItemDelegate.sizeHint implementation """ options = QStyleOptionViewItem(option) self.initStyleOption(options, index) doc = QTextDocument() if self._font is not None: doc.setDefaultFont(self._font) doc.setDocumentMargin(1) # bad long (multiline) strings processing doc.setTextWidth(options.rect.width()) doc.setHtml(options.text) return QSize(doc.idealWidth(), doc.size().height())
class Task(object): font = QFont('Decorative', 10) labelW, labelH = 20, 20 pen = QPen(Qt.black, 0.5, Qt.DashLine) dotSize = 18 def __init__(self, tid, taskInfo, drawingInputs): self.tid = tid # self.plabel, self.dlabel = QTextDocument(), QTextDocument() self.plabel.setHtml("%d<sup>+</sup>" % self.tid) self.dlabel.setHtml("%d<sup>-</sup>" % self.tid) self.plabel.setDefaultFont(Task.font) self.dlabel.setDefaultFont(Task.font) # pLocXY, dLocXY, pTW_Xs, dTW_Xs, self.coX4GC, self.oriY_GC, self.yUnit = drawingInputs self.ppX, self.ppY = pLocXY self.dpX, self.dpY = dLocXY self.pTW_rect = self.get_twRect(pTW_Xs, isPickupTW=True) self.dTW_rect = self.get_twRect(dTW_Xs, isPickupTW=False) def get_twRect(self, tw, isPickupTW=False): a, b = tw return QRectF( a, self.oriY_GC if isPickupTW else self.oriY_GC + self.yUnit, b - a, self.yUnit) def draw(self, qp): for cx, cy, label in [(self.ppX, self.ppY, self.plabel), (self.dpX, self.dpY, self.dlabel)]: drawLabel(qp, label, cx, cy, Task.labelW, Task.labelH) qp.setPen(Task.pen) qp.setBrush(Qt.NoBrush) for f, (p0, p1) in [(qp.drawEllipse, (self.ppX, self.ppY)), (qp.drawRect, (self.dpX, self.dpY))]: f(p0 - Task.dotSize / 2, p1 - Task.dotSize / 2, Task.dotSize, Task.dotSize) # pen = QPen(Qt.black, 1, Qt.SolidLine) qp.setPen(pen) qp.setBrush(Qt.NoBrush) for cx, cy, label in [ (self.coX4GC - hMargin * 2.0, vMargin * 3 + self.oriY_GC, self.plabel), (self.coX4GC - hMargin * 2.0, vMargin * 3 + self.oriY_GC + self.yUnit, self.dlabel) ]: drawLabel(qp, label, cx, cy, Task.labelW, Task.labelH) qp.drawRect(self.pTW_rect) qp.drawRect(self.dTW_rect)
def paint(self, painter: QPainter, option, index): # reference following link # https://stackoverflow.com/questions/53353450/how-to-highlight-a-words-in-qtablewidget-from-a-searchlist # https://stackoverflow.com/questions/34623036/implementing-a-delegate-for-wordwrap-in-a-qtreeview-qt-pyside-pyqt painter.save() doc = QTextDocument(self) # option.palette.setColor(QPalette.HighlightedText, QColor.fromRgb(30, 136, 200)) # remove dotted border in table if option.state & QStyle.State_HasFocus: option.state = option.state ^ QStyle.State_HasFocus options = QStyleOptionViewItem(option) self.initStyleOption(options, index) doc.setPlainText(options.text) # keyword = index.data(Qt.UserRole) # if self.keywords: self.keywordHighlight(doc) options.text = "" # print(dir(options.palette)) # print(options.palette.Highlight) style = QApplication.style() if options.widget is None \ else options.widget.style() style.drawControl(QStyle.CE_ItemViewItem, options, painter, options.widget) # for selection highlight ctx = QAbstractTextDocumentLayout.PaintContext() if index.data(Qt.UserRole) == 'reserved': ctx.palette.setColor(QPalette.Text, QColor.fromRgb(100, 100, 100)) doc.setDefaultFont( QFont(option.font.family(), option.font.pointSize() * 2 // 3)) else: ctx.palette.setColor(QPalette.Text, QColor.fromRgb(217, 217, 217)) doc.setDefaultFont(option.font) textRect = option.rect # margin = 4 # textRect.setTop(textRect.top() + margin) textRect.setTop(textRect.top()) painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) doc.setTextWidth(option.rect.width()) doc.documentLayout().draw(painter, ctx) painter.restore()
def html_copy(cursor, scheme='editor', number_lines=False): """Return a new QTextDocument with highlighting set as HTML textcharformats. The cursor is a cursor of a document.Document instance. If the cursor has a selection, only the selection is put in the new document. If number_lines is True, line numbers are added. """ data = textformats.formatData(scheme) doc = QTextDocument() doc.setDefaultFont(data.font) doc.setPlainText(cursor.document().toPlainText()) if metainfo.info(cursor.document()).highlighting: highlight(doc, mapping(data), ly.lex.state(documentinfo.mode(cursor.document()))) if cursor.hasSelection(): # cut out not selected text start, end = cursor.selectionStart(), cursor.selectionEnd() cur1 = QTextCursor(doc) cur1.setPosition(start, QTextCursor.KeepAnchor) cur2 = QTextCursor(doc) cur2.setPosition(end) cur2.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) cur2.removeSelectedText() cur1.removeSelectedText() if number_lines: c = QTextCursor(doc) f = QTextCharFormat() f.setBackground(QColor('#eeeeee')) if cursor.hasSelection(): num = cursor.document().findBlock( cursor.selectionStart()).blockNumber() + 1 last = cursor.document().findBlock(cursor.selectionEnd()) else: num = 1 last = cursor.document().lastBlock() lastnum = last.blockNumber() + 1 padding = len(format(lastnum)) block = doc.firstBlock() while block.isValid(): c.setPosition(block.position()) c.setCharFormat(f) c.insertText('{0:>{1}d} '.format(num, padding)) block = block.next() num += 1 return doc
def html_copy(cursor, scheme='editor', number_lines=False): """Return a new QTextDocument with highlighting set as HTML textcharformats. The cursor is a cursor of a document.Document instance. If the cursor has a selection, only the selection is put in the new document. If number_lines is True, line numbers are added. """ data = textformats.formatData(scheme) doc = QTextDocument() doc.setDefaultFont(data.font) doc.setPlainText(cursor.document().toPlainText()) if metainfo.info(cursor.document()).highlighting: highlight(doc, mapping(data), ly.lex.state(documentinfo.mode(cursor.document()))) if cursor.hasSelection(): # cut out not selected text start, end = cursor.selectionStart(), cursor.selectionEnd() cur1 = QTextCursor(doc) cur1.setPosition(start, QTextCursor.KeepAnchor) cur2 = QTextCursor(doc) cur2.setPosition(end) cur2.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) cur2.removeSelectedText() cur1.removeSelectedText() if number_lines: c = QTextCursor(doc) f = QTextCharFormat() f.setBackground(QColor('#eeeeee')) if cursor.hasSelection(): num = cursor.document().findBlock(cursor.selectionStart()).blockNumber() + 1 last = cursor.document().findBlock(cursor.selectionEnd()) else: num = 1 last = cursor.document().lastBlock() lastnum = last.blockNumber() + 1 padding = len(format(lastnum)) block = doc.firstBlock() while block.isValid(): c.setPosition(block.position()) c.setCharFormat(f) c.insertText('{0:>{1}d} '.format(num, padding)) block = block.next() num += 1 return doc
def paint(self, painter, option, index): text = index.model().data(index, Qt.DisplayRole) palette = QApplication.palette() document = QTextDocument() document.setDefaultFont(option.font) if option.state & QStyle.State_Selected: document.setHtml("<font color={0}>{1}</font>".format( palette.highlightedText().color().name(), text)) else: document.setHtml(text) painter.save() color = (palette.highlight().color() if option.state & QStyle.State_Selected else QColor(index.model().data( index, Qt.BackgroundColorRole))) painter.fillRect(option.rect, color) painter.translate(option.rect.x(), option.rect.y()) document.drawContents(painter) painter.restore()
def print_proof(self): printer = QPrinter(96) printer.setOrientation(QPrinter.Landscape) printer.setOutputFileName('tmp.pdf') printer.setPageMargins(16, 12, 20, 12, QPrinter.Millimeter) text = "Date:\n{}\n\n".format(time.strftime("%d/%m/%Y")) text += "Address:\n{}\n\n".format(self.api.get_main_address()) text += "Current Blockhash:\n{}".format(self.api.get_actual_hash()) document = QTextDocument() document.setPageSize(QSizeF(printer.pageRect().size())) document.setDefaultFont(QFont("Arial", 30)) document.setPlainText(text) dialog = QPrintDialog() if dialog.exec_() == QDialog.Accepted: dialog.printer().setOrientation(QPrinter.Landscape) document.print_(dialog.printer())
def headerFooterDoc(self, header=True, pageNum=1, numPages=1): """Return a text document for the header or footer. Return None if no header/footer is defined. Arguments: header -- return header if True, footer if false """ text = self.formatHeaderFooter(header, pageNum, numPages) if text: doc = QTextDocument() doc.setHtml(text) doc.setDefaultFont(self.mainFont) frameFormat = doc.rootFrame().frameFormat() frameFormat.setBorder(0) frameFormat.setMargin(0) frameFormat.setPadding(0) doc.rootFrame().setFrameFormat(frameFormat) return doc return None
def sizeHint(self, option, index): msg = index.model().data(index, Qt.DisplayRole) field = QRect(option.rect) field.setWidth(variables.window_width - variables.WINDOW_PADDING) field = field.marginsRemoved(variables.TEXT_PADDING) doc = QTextDocument(msg.text) doc.setDocumentMargin(0) opt = QTextOption() opt.setWrapMode(opt.WrapAtWordBoundaryOrAnywhere) doc.setDefaultTextOption(opt) doc.setDefaultFont(variables.font) if msg.user == variables.USER_ME: doc.setTextWidth(field.size().width() - 20 - 50) else: doc.setTextWidth(field.size().width() - 20) field.setHeight(int(doc.size().height())) field.setWidth(int(doc.idealWidth())) field = field.marginsAdded(variables.TEXT_PADDING) return QSize(0, field.size().height())
def get_max_left_label_width(self): doc = QTextDocument(self) doc.setDocumentMargin(0) doc.setDefaultFont(self.lblOwnerKey.font()) doc.setHtml('Test') def get_lbl_text_width(lbl): nonlocal doc doc.setHtml(lbl.text()) return int(doc.size().width() + 5) w = max(get_lbl_text_width(self.lblName), get_lbl_text_width(self.lblIP), get_lbl_text_width(self.lblCollateral), get_lbl_text_width(self.lblCollateralTxHash), get_lbl_text_width(self.lblDMNTxHash), get_lbl_text_width(self.lblOwnerKey), get_lbl_text_width(self.lblOperatorKey), get_lbl_text_width(self.lblVotingKey)) return w
def paint(self, painter, option, index): """QStyledItemDelegate.paint implementation """ option.state &= ~QStyle.State_HasFocus # never draw focus rect options = QStyleOptionViewItem(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) if options.widget is not None: doc.setDefaultFont(options.widget.font()) # 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()) """Original example contained line painter.setClipRect(textRect.translated(-textRect.topLeft())) but text is drawn clipped with it on kubuntu 12.04 """ doc.documentLayout().draw(painter, ctx) painter.restore()
def __init__(self, aid, agentInfo, drawingInputs): self.aid = aid self.agentInfo, self.drawingInputs = agentInfo, drawingInputs # self.prep_trajDrawing() self.oLabels, self.dLabels = [], [] self.luLabels = [] for r, (_, timeBudget, oLoc, seqLocs, dLoc) in enumerate(agentInfo): label = QTextDocument() label.setHtml("o<sup>%d</sup><sub>%d</sub>" % (self.aid, r)) label.setDefaultFont(Task.font) self.oLabels.append(label) label = QTextDocument() label.setHtml("d<sup>%d</sup><sub>%d</sub>" % (self.aid, r)) label.setDefaultFont(Task.font) self.dLabels.append(label) # locS = [oLoc] for loc in seqLocs: locS.append(loc) locS.append(dLoc) dist = 0.0 for i in range(len(locS) - 1): dist += np.linalg.norm(locS[i] - locS[i + 1]) label = QTextDocument() label.setHtml( "RR<sup>%d</sup><sub>%d</sub>=%.2f u<sup>%d</sup><sub>%d</sub>=%.2f" % (self.aid, r, dist, self.aid, r, timeBudget)) label.setDefaultFont(Task.font) self.luLabels.append(label)
def documentFromDockerfile(self, filename): doc = QTextDocument(self) doc.setDocumentLayout(QtWidgets.QPlainTextDocumentLayout(doc)) if filename == "-SCRATCH-": doc.setPlainText("") else: with open(filename, 'r') as f: doc.setPlainText(f.read()) doc.setDefaultFont(self.fontDockerfileEditor) doc.highlighter = DockerSyntaxHighlighter(doc) #doc.modificationChanged[bool].connect(self.onModificationChanged) doc.setModified(False) self._cachedDocument = doc self.txtDockerfile.setDocument(doc) plainText = self.txtDockerfile.toPlainText() if self._find_bioclite(self.FLAG_binder_string, plainText): self.FLAG_binder_compatible = True else: self.FLAG_binder_compatible = False return self._cachedDocument
def paint(self, painter, option, index): if index.column() == DESCRIPTION: text = str(index.model().data(index)) palette = QApplication.palette() document = QTextDocument() document.setDefaultFont(option.font) if option.state & QStyle.State_Selected: # document.setHtml("<font color={0}>{1}</font>".format("#FF0000",text)) document.setHtml("<font color={0}>{1}</font>".format( palette.highlightedText().color().name(), text)) else: document.setHtml(text) color = (palette.highlight().color() if option.state & QStyle.State_Selected else QColor(index.model().data( index, Qt.BackgroundColorRole))) # print(palette.highlight().color().name()) painter.save() painter.fillRect(option.rect, color) painter.translate(option.rect.x(), option.rect.y()) document.drawContents(painter) painter.restore() else: QStyledItemDelegate.paint(self, painter, option, index)
def paint(self, painter, option, index): """QStyledItemDelegate.paint implementation """ option.state &= ~QStyle.State_HasFocus # never draw focus rect option.state |= QStyle.State_Active # draw fuzzy-open completion as focused, even if focus is on the line edit options = QStyleOptionViewItem(option) self.initStyleOption(options, index) style = QApplication.style() if options.widget is None else options.widget.style() doc = QTextDocument() if self._font is not None: doc.setDefaultFont(self._font) 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.Text)) 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 = QStyleOptionViewItem(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) if options.widget is not None: doc.setDefaultFont(options.widget.font()) # 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()) """Original example contained line painter.setClipRect(textRect.translated(-textRect.topLeft())) but text is drawn clipped with it on kubuntu 12.04 """ doc.documentLayout().draw(painter, ctx) painter.restore()
class OutputItem: """Class to store output for a single node. Stores text lines and original indent level. """ def __init__(self, spot, level): """Convert the spot's node into an output item. Create a blank item if spot is None. Arguments: spot -- the tree spot to convert level -- the node's original indent level """ if spot: node = spot.nodeRef nodeFormat = node.formatRef if not nodeFormat.useTables: self.textLines = [ line + '<br />' for line in node.output(spotRef=spot) ] else: self.textLines = node.output(keepBlanks=True, spotRef=spot) if not self.textLines: self.textLines = [''] self.addSpace = nodeFormat.spaceBetween self.siblingPrefix = nodeFormat.siblingPrefix self.siblingSuffix = nodeFormat.siblingSuffix if nodeFormat.useBullets and self.textLines: # remove <br /> extra space for bullets self.textLines[-1] = self.textLines[-1][:-6] self.uId = node.uId else: self.textLines = [''] self.addSpace = False self.siblingPrefix = '' self.siblingSuffix = '' self.uId = None self.level = level # following variables used by printdata only: self.height = 0 self.pageNum = 0 self.columnNum = 0 self.pagePos = 0 self.doc = None self.parentItem = None self.lastChildItem = None def duplicate(self): """Return an independent copy of this OutputItem. """ item = OutputItem(None, 0) item.textLines = self.textLines[:] item.addSpace = self.addSpace item.siblingPrefix = self.siblingPrefix item.siblingSuffix = self.siblingSuffix item.uId = self.uId item.level = self.level item.height = self.height item.pageNum = self.pageNum item.columnNum = self.columnNum item.pagePos = self.pagePos item.doc = None item.parentItem = self.parentItem item.lastChildItem = self.lastChildItem return item def addIndent(self, prevLevel, nextLevel): """Add <div> tags to define indent levels in the output. Arguments: prevLevel -- the level of the previous item in the list nextLevel -- the level of the next item in the list """ for num in range(self.level - prevLevel): self.textLines[0] = '<div>' + self.textLines[0] for num in range(self.level - nextLevel): self.textLines[-1] += '</div>' def addAbsoluteIndent(self, pixels): """Add tags for an individual indentation. Removes the <br /> tag from the last line to avoid excess space, since <div> starts a new line. The Qt output view does not fully support nested <div> tags. Arguments: pixels -- the amount to indent """ self.textLines[0] = ('<div style="margin-left: {0}">{1}'.format( pixels * self.level, self.textLines[0])) if not self.siblingPrefix and self.textLines[-1].endswith('<br />'): self.textLines[-1] = self.textLines[-1][:-6] self.textLines[-1] += '</div>' def addSiblingPrefix(self): """Add the sibling prefix before this output. """ if self.siblingPrefix: self.textLines[0] = self.siblingPrefix + self.textLines[0] def addSiblingSuffix(self): """Add the sibling suffix after this output. """ if self.siblingSuffix: self.textLines[-1] += self.siblingSuffix def addAnchor(self): """Add a link anchor to this item. """ self.textLines[0] = '<a id="{0}" />{1}'.format(self.uId, self.textLines[0]) def intLinkIds(self): """Return a set of uIDs from any internal links in this item. """ linkIds = set() for line in self.textLines: startPos = 0 while True: match = _linkRe.search(line, startPos) if not match: break uId = match.group(1) if uId: linkIds.add(uId) startPos = match.start(1) return linkIds def numLines(self): """Return the number of text lines in the item. """ return len(self.textLines) def equalPrefix(self, otherItem): """Return True if sibling prefixes and suffixes are equal. Arguments: otherItem -- the item to compare """ return (self.siblingPrefix == otherItem.siblingPrefix and self.siblingSuffix == otherItem.siblingSuffix) def setDocHeight(self, paintDevice, width, printFont, replaceDoc=False): """Set the height of this item for use in printer output. Creates an output document if not already created. Arguments: paintDevice -- the printer or other device for settings width -- the width available for the output text printFont -- the default font for the document replaceDoc -- if true, re-create the text document """ if not self.doc or replaceDoc: self.doc = QTextDocument() lines = '\n'.join(self.textLines) if lines.endswith('<br />'): # remove trailing <br /> tag to avoid excess space lines = lines[:-6] self.doc.setHtml(lines) self.doc.setDefaultFont(printFont) frameFormat = self.doc.rootFrame().frameFormat() frameFormat.setBorder(0) frameFormat.setMargin(0) frameFormat.setPadding(0) self.doc.rootFrame().setFrameFormat(frameFormat) layout = self.doc.documentLayout() layout.setPaintDevice(paintDevice) self.doc.setTextWidth(width) self.height = layout.documentSize().height() def splitDocHeight(self, initHeight, maxHeight, paintDevice, width, printFont): """Split this item into two items and return them. The first item will fit into initHeight if practical. Splits at line endings if posible. Arguments: initHeight -- the preferred height of the first page maxheight -- the max height of any pages paintDevice -- the printer or other device for settings width -- the width available for the output text printFont -- the default font for the document """ newItem = self.duplicate() fullHeight = self.height lines = '\n'.join(self.textLines) allLines = [line + '<br />' for line in lines.split('<br />')] self.textLines = [] prevHeight = 0 for line in allLines: self.textLines.append(line) self.setDocHeight(paintDevice, width, printFont, True) if ((prevHeight and self.height > initHeight and fullHeight - prevHeight > maxHeight) or (prevHeight and self.height > maxHeight)): self.textLines = self.textLines[:-1] self.setDocHeight(paintDevice, width, printFont, True) newItem.textLines = allLines[len(self.textLines):] newItem.setDocHeight(paintDevice, width, printFont, True) return (self, newItem) if self.height > maxHeight: break prevHeight = self.height # no line ending breaks found text = ' \n'.join(allLines) allWords = [word + ' ' for word in text.split(' ')] newWords = [] prevHeight = 0 for word in allWords: if word.strip() == '<img': break newWords.append(word) self.textLines = [''.join(newWords)] self.setDocHeight(paintDevice, width, printFont, True) if ((prevHeight and self.height > initHeight and fullHeight - prevHeight < maxHeight) or (prevHeight and self.height > maxHeight)): self.textLines = [''.join(newWords[:-1])] self.setDocHeight(paintDevice, width, printFont, True) newItem.textLines = [''.join(allWords[len(newWords):])] newItem.setDocHeight(paintDevice, width, printFont, True) return (self, newItem) if self.height > maxHeight: break prevHeight = self.height newItem.setDocHeight(paintDevice, width, printFont, True) return (newItem, None) # fail to split
def paint(self, painter, option, index): msg = index.model().data(index, Qt.DisplayRole) field = QRect(option.rect) field = field.marginsRemoved(variables.TEXT_PADDING) doc = QTextDocument(msg.text) doc.setDocumentMargin(0) opt = QTextOption() opt.setWrapMode(opt.WrapAtWordBoundaryOrAnywhere) doc.setDefaultTextOption(opt) doc.setDefaultFont(variables.font) if msg.user == variables.USER_ME: doc.setTextWidth(field.size().width() - 20 - 50) else: doc.setTextWidth(field.size().width() - 20) field.setHeight(int(doc.size().height())) field.setWidth(int(doc.idealWidth())) field = field.marginsAdded(variables.TEXT_PADDING) line_height = QFontMetrics(variables.font).lineSpacing( ) + variables.TEXT_PADDING.bottom() - variables.BUBBLE_PADDING.bottom( ) + variables.TEXT_PADDING.top() - variables.BUBBLE_PADDING.top() if msg.user == variables.USER_ME: rect = QRect(option.rect.right() - field.size().width() - 20, option.rect.top(), field.size().width(), field.size().height()) else: rect = QRect(20, option.rect.top(), field.size().width(), field.size().height()) bubblerect = rect.marginsRemoved(variables.BUBBLE_PADDING) textrect = rect.marginsRemoved(variables.TEXT_PADDING) if msg.user == variables.USER_ME: p1 = bubblerect.topRight() p2 = bubblerect.bottomLeft() + QPoint(-36, -int(line_height / 2)) else: p1 = bubblerect.topLeft() painter.setRenderHint(QPainter.Antialiasing) painter.setPen(Qt.NoPen) color = QColor(variables.BUBBLE_COLORS[msg.user]) painter.setBrush(color) painter.drawRoundedRect(bubblerect, 10, 10) painter.drawPolygon(p1 + QPoint(-20, 0), p1 + QPoint(20, 0), p1 + QPoint(0, 15)) if msg.user == variables.USER_ME: if msg.status == variables.STATUS_UNREAD: painter.setPen(Qt.NoPen) painter.setBrush(QColor(variables.STATUS_COLOR)) painter.drawEllipse(p2, 7, 7) elif msg.status == variables.STATUS_UNDELIVERED: pen = QPen(QColor(variables.STATUS_COLOR)) pen.setWidth(2) painter.setPen(pen) painter.setBrush(Qt.NoBrush) painter.drawEllipse(p2, 7, 7) painter.drawLine(p2, p2 + QPoint(0, -5)) painter.drawLine(p2, p2 + QPoint(3, 0)) painter.setPen(Qt.gray) painter.setFont(variables.font) painter.translate(textrect.x(), textrect.y()) textrectf = QRectF(textrect) textrectf.moveTo(0, 0) doc.drawContents(painter, textrectf) painter.translate(-textrect.x(), -textrect.y())
class Viz(QWidget): font = QFont('Decorative', 15) labelH = 30 unit_labelW = 15 def __init__(self, fpaths=None): super().__init__() self.app_name = 'Viz' self.fpaths = fpaths self.objForDrawing = [] # self.mousePressed = False self.px, self.py = -1, -1 # self.init_drawing() self.initUI() # self.shortcut = QShortcut(QKeySequence('Ctrl+W'), self) self.shortcut.activated.connect(self.close) def initUI(self): self.setGeometry(FRAME_ORIGIN[0], FRAME_ORIGIN[1], WIDTH, HEIGHT) self.setWindowTitle(self.app_name) self.setFixedSize(QSize(WIDTH, HEIGHT)) # self.image = QImage(WIDTH, HEIGHT, QImage.Format_RGB32) self.image.fill(Qt.white) pal = self.palette() pal.setColor(QPalette.Background, Qt.white) self.setAutoFillBackground(True) self.setPalette(pal) # self.show() def save_img(self): self.image.save('temp.png', 'png') def paintEvent(self, e): for canvas in [self, self.image]: qp = QPainter() qp.begin(canvas) self.drawCanvas(qp) qp.end() def drawCanvas(self, qp): for o in self.objForDrawing: o.draw(qp) if self.mousePressed: qp.translate(self.px, self.py) self.selDistLabel.drawContents( qp, QRectF(0, 0, self.labelW, Viz.labelH)) qp.translate(-self.px, -self.py) def init_drawing(self): sgBoarderXY = [] for poly in sgBorder: sgBorderPartial_xy = [] for lat, lng in poly: x, y = convert_GPS2xy(lng, lat) sgBorderPartial_xy += [(x, y)] sgBoarderXY.append(sgBorderPartial_xy) sgDistrictXY = {} distPoly = get_distPoly() for dist_name, poly in distPoly.items(): points = [] for lat, lng in poly: points.append(convert_GPS2xy(lng, lat)) sgDistrictXY[dist_name] = points self.sg = Singapore(sgBoarderXY, sgDistrictXY) self.objForDrawing = [self.sg] # self.gzs = {} lats, lngs = get_sgGrid() for i, j in get_validGrid(): lng0, lng1 = lngs[i], lngs[i + 1] lat0, lat1 = lats[j], lats[j + 1] cLng, cLat = (lng0 + lng1) / 2.0, (lat0 + lat1) / 2.0 # zid = '(%d,%d)' % (i, j) cp = QPointF(*convert_GPS2xy(cLng, cLat)) rect = QRectF(QPointF(*convert_GPS2xy(lng0, lat1)), QPointF(*convert_GPS2xy(lng1, lat0))) gz = GridZone(zid, cp, rect) self.gzs[i, j] = gz self.objForDrawing.append(gz) if self.fpaths: with open(self.fpaths['AGTK'], 'rb') as fp: agents, tasks = pickle.load(fp) for tk in tasks: zi, zj = bisect(lngs, tk['LngD']) - 1, bisect( lats, tk['LatD']) - 1 z = self.gzs[zi, zj] z.increaseCounter() if SHOW_AGENT: for agt in agents: RRs = [] for aRR in agt['RRs']: trajXY = [] for mvt in aRR['mvts']: trajXY.append([ convert_GPS2xy(lng, lat) for lat, lng in mvt['traj'] ]) RRs.append([aRR['prob'], trajXY]) self.objForDrawing.append( Agent(agt['aid'], agt['cid'], RRs)) for tk in tasks: pcx, pcy = convert_GPS2xy(tk['LngP'], tk['LatP']) dcx, dcy = convert_GPS2xy(tk['LngD'], tk['LatD']) self.objForDrawing.append( Task(tk['tid'], [pcx, pcy], [dcx, dcy])) def mousePressEvent(self, QMouseEvent): if self.mousePressed: self.mousePressed = False self.px, self.py = -1, -1 self.update() else: pos = QMouseEvent.pos() x, y = [f() for f in [pos.x, pos.y]] dist_name = self.sg.get_distName(x, y) if dist_name: self.mousePressed = True self.selDistLabel = QTextDocument() self.selDistLabel.setHtml(dist_name) self.selDistLabel.setDefaultFont(Viz.font) self.labelW = len(dist_name) * Viz.unit_labelW self.px, self.py = x - self.labelW / 2, y - Viz.labelH print(dist_name) self.update()
def paint(self, painter, option, index): assert isinstance(painter, QPainter) if index.data(Qt.UserRole+1): if app_constants.HIGH_QUALITY_THUMBS: painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.setRenderHint(QPainter.Antialiasing) gallery = index.data(Qt.UserRole+1) title = gallery.title artist = gallery.artist title_color = app_constants.GRID_VIEW_TITLE_COLOR artist_color = app_constants.GRID_VIEW_ARTIST_COLOR label_color = app_constants.GRID_VIEW_LABEL_COLOR # Enable this to see the defining box #painter.drawRect(option.rect) # define font size if 20 > len(title) > 15: title_size = "font-size:{}px;".format(self.font_size) elif 30 > len(title) > 20: title_size = "font-size:{}px;".format(self.font_size-1) elif 40 > len(title) >= 30: title_size = "font-size:{}px;".format(self.font_size-2) elif 50 > len(title) >= 40: title_size = "font-size:{}px;".format(self.font_size-3) elif len(title) >= 50: title_size = "font-size:{}px;".format(self.font_size-4) else: title_size = "font-size:{}px;".format(self.font_size) if 30 > len(artist) > 20: artist_size = "font-size:{}px;".format(self.font_size) elif 40 > len(artist) >= 30: artist_size = "font-size:{}px;".format(self.font_size-1) elif len(artist) >= 40: artist_size = "font-size:{}px;".format(self.font_size-2) else: artist_size = "font-size:{}px;".format(self.font_size) #painter.setPen(QPen(Qt.NoPen)) #option.rect = option.rect.adjusted(11, 10, 0, 0) option.rect.setWidth(self.W) option.rect.setHeight(self.H) rec = option.rect.getRect() x = rec[0] y = rec[1] w = rec[2] h = rec[3] text_area = QTextDocument() text_area.setDefaultFont(option.font) text_area.setHtml(""" <head> <style> #area {{ display:flex; width:140px; height:10px }} #title {{ position:absolute; color: {4}; font-weight:bold; {0} }} #artist {{ position:absolute; color: {5}; top:20px; right:0; {1} }} </style> </head> <body> <div id="area"> <center> <div id="title">{2} </div> <div id="artist">{3} </div> </div> </center> </body> """.format(title_size, artist_size, title, artist, title_color, artist_color)) text_area.setTextWidth(w) #chapter_area = QTextDocument() #chapter_area.setDefaultFont(option.font) #chapter_area.setHtml(""" #<font color="black">{}</font> #""".format("chapter")) #chapter_area.setTextWidth(w) def center_img(width): new_x = x if width < w: diff = w - width offset = diff//2 new_x += offset return new_x # if we can't find a cached image pix_cache = QPixmapCache.find(self.key(gallery.profile)) if isinstance(pix_cache, QPixmap): self.image = pix_cache img_x = center_img(self.image.width()) if self.image.height() < self.image.width(): #to keep aspect ratio painter.drawPixmap(QPoint(img_x,y), self.image) else: painter.drawPixmap(QPoint(img_x,y), self.image) else: self.image = QPixmap(gallery.profile) img_x = center_img(self.image.width()) QPixmapCache.insert(self.key(gallery.profile), self.image) if self.image.height() < self.image.width(): #to keep aspect ratio painter.drawPixmap(QPoint(img_x,y), self.image) else: painter.drawPixmap(QPoint(img_x,y), self.image) # draw star if it's favorited if gallery.fav == 1: painter.drawPixmap(QPointF(x,y), QPixmap(app_constants.STAR_PATH)) if app_constants._REFRESH_EXTERNAL_VIEWER: if app_constants.USE_EXTERNAL_VIEWER: self.external_icon = self.file_icons.get_external_file_icon() else: self.external_icon = self.file_icons.get_default_file_icon() if gallery.state == self.G_DOWNLOAD: painter.save() dl_box = QRect(x, y, w, 20) painter.setBrush(QBrush(QColor(0,0,0,123))) painter.setPen(QColor('white')) painter.drawRect(dl_box) painter.drawText(dl_box, Qt.AlignCenter, 'Downloading...') painter.restore() else: if app_constants.DISPLAY_GALLERY_TYPE: self.type_icon = self.file_icons.get_file_icon(gallery.path) if self.type_icon and not self.type_icon.isNull(): self.type_icon.paint(painter, QRect(x+2, y+app_constants.THUMB_H_SIZE-16, 16, 16)) if app_constants.USE_EXTERNAL_PROG_ICO: if self.external_icon and not self.external_icon.isNull(): self.external_icon.paint(painter, QRect(x+w-30, y+app_constants.THUMB_H_SIZE-28, 28, 28)) def draw_text_label(lbl_h): #draw the label for text painter.save() painter.translate(x, y+app_constants.THUMB_H_SIZE) box_color = QBrush(QColor(label_color))#QColor(0,0,0,123)) painter.setBrush(box_color) rect = QRect(0, 0, w, lbl_h) #x, y, width, height painter.fillRect(rect, box_color) painter.restore() return rect if option.state & QStyle.State_MouseOver or\ option.state & QStyle.State_Selected: title_layout = self.text_layout(title, w, self.title_font, self.title_font_m) artist_layout = self.text_layout(artist, w, self.artist_font, self.artist_font_m) t_h = title_layout.boundingRect().height() a_h = artist_layout.boundingRect().height() if app_constants.GALLERY_FONT_ELIDE: lbl_rect = draw_text_label(min(t_h+a_h+3, app_constants.GRIDBOX_LBL_H)) else: lbl_rect = draw_text_label(app_constants.GRIDBOX_LBL_H) clipping = QRectF(x, y+app_constants.THUMB_H_SIZE, w, app_constants.GRIDBOX_LBL_H - 10) title_layout.draw(painter, QPointF(x, y+app_constants.THUMB_H_SIZE), clip=clipping) artist_layout.draw(painter, QPointF(x, y+app_constants.THUMB_H_SIZE+t_h), clip=clipping) #painter.fillRect(option.rect, QColor) else: if app_constants.GALLERY_FONT_ELIDE: lbl_rect = draw_text_label(self.text_label_h) else: lbl_rect = draw_text_label(app_constants.GRIDBOX_LBL_H) # draw text painter.save() alignment = QTextOption(Qt.AlignCenter) alignment.setUseDesignMetrics(True) title_rect = QRectF(0,0,w, self.title_font_m.height()) artist_rect = QRectF(0,self.artist_font_m.height(),w, self.artist_font_m.height()) painter.translate(x, y+app_constants.THUMB_H_SIZE) if app_constants.GALLERY_FONT_ELIDE: painter.setFont(self.title_font) painter.setPen(QColor(title_color)) painter.drawText(title_rect, self.title_font_m.elidedText(title, Qt.ElideRight, w-10), alignment) painter.setPen(QColor(artist_color)) painter.setFont(self.artist_font) alignment.setWrapMode(QTextOption.NoWrap) painter.drawText(artist_rect, self.title_font_m.elidedText(artist, Qt.ElideRight, w-10), alignment) else: text_area.setDefaultFont(QFont(self.font_name)) text_area.drawContents(painter) ##painter.resetTransform() painter.restore() if option.state & QStyle.State_Selected: painter.save() selected_rect = QRectF(x, y, w, lbl_rect.height()+app_constants.THUMB_H_SIZE) painter.setPen(Qt.NoPen) painter.setBrush(QBrush(QColor(164,164,164,120))) p_path = QPainterPath() p_path.setFillRule(Qt.WindingFill) p_path.addRoundedRect(selected_rect, 5,5) p_path.addRect(x,y, 20, 20) p_path.addRect(x+w-20,y, 20, 20) painter.drawPath(p_path.simplified()) #painter.fillRect(selected_rect, QColor(164,164,164,120)) painter.restore() #if option.state & QStyle.State_Selected: # painter.setPen(QPen(option.palette.highlightedText().color())) else: super().paint(painter, option, index)
class SyntaxHighlightDelegate(QStyledItemDelegate): def __init__(self, parent=None): super(SyntaxHighlightDelegate, self).__init__(parent) self.doc = QTextDocument(self) self.disasm_columns = [] self.value_columns = [] self.highlighted_regs = {} self.reg_hl_color = prefs.REG_HL_COLOR self.reg_hl_bg_colors = prefs.REG_HL_BG_COLORS self.ignored_chars = (" ", ",", "+", "[", "]") self.disasm_rules = self.load_rules_file(prefs.DISASM_RULES_FILE) self.value_rules = self.load_rules_file(prefs.VALUE_RULES_FILE) def load_rules_file(self, filename: str) -> list: """Loads syntax highlighting rules from json file""" with open(filename) as f: return json.load(f) def reset(self): """Resets highlighter""" self.highlighted_regs = {} def paint(self, painter, option, index): painter.save() options = QStyleOptionViewItem(option) self.initStyleOption(options, index) self.doc.setPlainText(options.text) column = index.column() if column in self.disasm_columns: options.font.setWeight(QFont.Bold) self.highlight(self.doc, self.disasm_rules) elif column in self.value_columns: options.font.setWeight(QFont.Bold) self.highlight(self.doc, self.value_rules) self.doc.setDefaultFont(options.font) options.text = "" style = (QApplication.style() if options.widget is None else options.widget.style()) style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() if option.state & QStyle.State_Selected: ctx.palette.setColor( QPalette.Text, option.palette.color(QPalette.Active, QPalette.HighlightedText), ) else: ctx.palette.setColor( QPalette.Text, option.palette.color(QPalette.Active, QPalette.Text), ) textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) if index.column() != 0: textRect.adjust(5, 0, 0, 0) the_constant = 4 margin = (option.rect.height() - options.fontMetrics.height()) // 2 margin = margin - the_constant textRect.setTop(textRect.top() + margin) painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) self.doc.documentLayout().draw(painter, ctx) painter.restore() def set_reg_highlight(self, reg: str, enabled: bool): """Enables or disables register highlight""" regs_hl = prefs.HL_REGS_X86 words = regs_hl.get(reg, [reg]) if enabled: self.highlighted_regs[reg] = words elif reg in self.highlighted_regs: del self.highlighted_regs[reg] def highlight(self, document: QTextDocument, rules: list): """Highlights document""" char_format = QTextCharFormat() cursor = QTextCursor(document) while not cursor.isNull() and not cursor.atEnd(): cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) text = cursor.selectedText() color, bgcolor = self.get_register_hl_color( text, self.highlighted_regs) if not color: color, bgcolor = self.get_color(text, rules) if color: char_format.setForeground(QColor(color)) if bgcolor: char_format.setBackground(QColor(bgcolor)) if color or bgcolor: cursor.mergeCharFormat(char_format) char_format.clearBackground() self.move_to_next_word(document, cursor) def move_to_next_word(self, doc: QTextDocument, cursor: QTextCursor): """Moves cursor to next word""" while not cursor.isNull() and not cursor.atEnd(): if doc.characterAt(cursor.position()) not in self.ignored_chars: return cursor.movePosition(QTextCursor.NextCharacter) def get_register_hl_color(self, word_to_check: str, regs_hl: dict) -> tuple: """Gets color and bgcolor if given word is found in regs_hl""" color_index = 0 for words in regs_hl.values(): if word_to_check in words: if color_index < len(self.reg_hl_bg_colors): bg_color = self.reg_hl_bg_colors[color_index] else: bg_color = self.reg_hl_bg_colors[-1] return (self.reg_hl_color, bg_color) color_index += 1 return ("", "") def get_color(self, word_to_check: str, rules: dict) -> tuple: """Gets color and bgcolor if given word is found in rules""" for rule in rules: if "words" in rule: for word in rule["words"]: if word == word_to_check: return (rule["color"], rule.get("bgcolor", "")) if "startswith" in rule: for sw in rule["startswith"]: if word_to_check.startswith(sw): return (rule["color"], rule.get("bgcolor", "")) if "has" in rule: for has in rule["has"]: if has in word_to_check: return (rule["color"], rule.get("bgcolor", "")) return ("", "")
class SyntaxHighlightDelegate(QStyledItemDelegate): def __init__(self, parent=None, arch: str = "x86", dark_theme: bool = False): super(SyntaxHighlightDelegate, self).__init__(parent) self.doc = QTextDocument(self) self.highlighted_columns = [3] self.syntax_colors = [] self.custom_hl = [] self.register_hl = {} if dark_theme: self.load_syntax_file("gui/syntax_hl/syntax_x86_dark.txt") self.reg_hl_color = QColor("#000000") self.reg_hl_bg_color = QColor("#ffffff") else: self.load_syntax_file("gui/syntax_hl/syntax_x86_light.txt") self.reg_hl_color = QColor("#ffffff") self.reg_hl_bg_color = QColor("#333333") def set_reg_highlight(self, reg: str, enabled: bool): regs_hl = prefs.HL_REGS_X86 words = regs_hl.get(reg, [reg]) if enabled: self.register_hl[reg] = words elif reg in self.register_hl: del self.register_hl[reg] def load_syntax_file(self, filename: str): with open(filename) as f: self.syntax_colors = json.load(f) def paint(self, painter, option, index): painter.save() options = QStyleOptionViewItem(option) self.initStyleOption(options, index) self.doc.setPlainText(options.text) if index.column() in self.highlighted_columns: options.font.setWeight(QFont.Bold) self.highlight() self.doc.setDefaultFont(options.font) options.text = "" style = ( QApplication.style() if options.widget is None else options.widget.style() ) style.drawControl(QStyle.CE_ItemViewItem, options, painter) ctx = QAbstractTextDocumentLayout.PaintContext() if option.state & QStyle.State_Selected: ctx.palette.setColor( QPalette.Text, option.palette.color(QPalette.Active, QPalette.HighlightedText), ) else: ctx.palette.setColor( QPalette.Text, option.palette.color(QPalette.Active, QPalette.Text), ) textRect = style.subElementRect(QStyle.SE_ItemViewItemText, options) if index.column() != 0: textRect.adjust(5, 0, 0, 0) the_constant = 4 margin = (option.rect.height() - options.fontMetrics.height()) // 2 margin = margin - the_constant textRect.setTop(textRect.top() + margin) painter.translate(textRect.topLeft()) painter.setClipRect(textRect.translated(-textRect.topLeft())) self.doc.documentLayout().draw(painter, ctx) painter.restore() def highlight(self): char_format = QTextCharFormat() cursor = QTextCursor(self.doc) while not cursor.isNull() and not cursor.atEnd(): cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor) color = self.get_register_hl_color(cursor.selectedText()) if color is not None: char_format.setBackground(self.reg_hl_bg_color) else: color = self.get_color(cursor.selectedText()) if color is not None: char_format.setForeground(color) cursor.mergeCharFormat(char_format) char_format.clearBackground() self.move_to_next_word(self.doc, cursor) def move_to_next_word(self, doc, cursor): while not cursor.isNull() and not cursor.atEnd(): if doc.characterAt(cursor.position()) not in (" ", ",", "+", "[", "]"): return cursor.movePosition(QTextCursor.NextCharacter) def get_register_hl_color(self, word_to_check: str): for words in self.register_hl.values(): if word_to_check in words: return QColor(self.reg_hl_color) return None def get_color(self, word_to_check: str): for syntax in self.syntax_colors: if "words" in syntax: for word in syntax["words"]: if word == word_to_check: return QColor(syntax["color"]) if "startswith" in syntax: for sw in syntax["startswith"]: if word_to_check.startswith(sw): return QColor(syntax["color"]) if "has" in syntax: for has in syntax["has"]: if has in word_to_check: return QColor(syntax["color"]) return None
def paint(self, painter, option, index): assert isinstance(painter, QPainter) if index.data(Qt.UserRole+1): if app_constants.HIGH_QUALITY_THUMBS: painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.setRenderHint(QPainter.Antialiasing) gallery = index.data(Qt.UserRole+1) title = gallery.title artist = gallery.artist title_color = app_constants.GRID_VIEW_TITLE_COLOR artist_color = app_constants.GRID_VIEW_ARTIST_COLOR label_color = app_constants.GRID_VIEW_LABEL_COLOR # Enable this to see the defining box #painter.drawRect(option.rect) # define font size if 20 > len(title) > 15: title_size = "font-size:{}px;".format(self.font_size) elif 30 > len(title) > 20: title_size = "font-size:{}px;".format(self.font_size-1) elif 40 > len(title) >= 30: title_size = "font-size:{}px;".format(self.font_size-2) elif 50 > len(title) >= 40: title_size = "font-size:{}px;".format(self.font_size-3) elif len(title) >= 50: title_size = "font-size:{}px;".format(self.font_size-4) else: title_size = "font-size:{}px;".format(self.font_size) if 30 > len(artist) > 20: artist_size = "font-size:{}px;".format(self.font_size) elif 40 > len(artist) >= 30: artist_size = "font-size:{}px;".format(self.font_size-1) elif len(artist) >= 40: artist_size = "font-size:{}px;".format(self.font_size-2) else: artist_size = "font-size:{}px;".format(self.font_size) #painter.setPen(QPen(Qt.NoPen)) #option.rect = option.rect.adjusted(11, 10, 0, 0) option.rect.setWidth(self.W) option.rect.setHeight(self.H) rec = option.rect.getRect() x = rec[0] y = rec[1] w = rec[2] h = rec[3] text_area = QTextDocument() text_area.setDefaultFont(option.font) text_area.setHtml(""" <head> <style> #area {{ display:flex; width:{6}px; height:{7}px }} #title {{ position:absolute; color: {4}; font-weight:bold; {0} }} #artist {{ position:absolute; color: {5}; top:20px; right:0; {1} }} </style> </head> <body> <div id="area"> <center> <div id="title">{2} </div> <div id="artist">{3} </div> </div> </center> </body> """.format(title_size, artist_size, title, artist, title_color, artist_color, 130+app_constants.SIZE_FACTOR, 1+app_constants.SIZE_FACTOR)) text_area.setTextWidth(w) #chapter_area = QTextDocument() #chapter_area.setDefaultFont(option.font) #chapter_area.setHtml(""" #<font color="black">{}</font> #""".format("chapter")) #chapter_area.setTextWidth(w) def center_img(width): new_x = x if width < w: diff = w - width offset = diff//2 new_x += offset return new_x def img_too_big(start_x): txt_layout = misc.text_layout("Image is too big!", w, self.title_font, self.title_font_m) clipping = QRectF(x, y+h//4, w, app_constants.GRIDBOX_LBL_H - 10) txt_layout.draw(painter, QPointF(x, y+h//4), clip=clipping) # if we can't find a cached image pix_cache = QPixmapCache.find(self.key(gallery.profile)) if isinstance(pix_cache, QPixmap): self.image = pix_cache img_x = center_img(self.image.width()) if self.image.width() > w or self.image.height() > h: img_too_big(img_x) else: if self.image.height() < self.image.width(): #to keep aspect ratio painter.drawPixmap(QPoint(img_x,y), self.image) else: painter.drawPixmap(QPoint(img_x,y), self.image) else: self.image = QPixmap(gallery.profile) img_x = center_img(self.image.width()) QPixmapCache.insert(self.key(gallery.profile), self.image) if self.image.width() > w or self.image.height() > h: img_too_big(img_x) else: if self.image.height() < self.image.width(): #to keep aspect ratio painter.drawPixmap(QPoint(img_x,y), self.image) else: painter.drawPixmap(QPoint(img_x,y), self.image) # draw ribbon type painter.save() painter.setPen(Qt.NoPen) if app_constants.DISPLAY_GALLERY_RIBBON: type_ribbon_w = type_ribbon_l = w*0.11 rib_top_1 = QPointF(x+w-type_ribbon_l-type_ribbon_w, y) rib_top_2 = QPointF(x+w-type_ribbon_l, y) rib_side_1 = QPointF(x+w, y+type_ribbon_l) rib_side_2 = QPointF(x+w, y+type_ribbon_l+type_ribbon_w) ribbon_polygon = QPolygonF([rib_top_1, rib_top_2, rib_side_1, rib_side_2]) ribbon_path = QPainterPath() ribbon_path.setFillRule(Qt.WindingFill) ribbon_path.addPolygon(ribbon_polygon) ribbon_path.closeSubpath() painter.setBrush(QBrush(QColor(self._ribbon_color(gallery.type)))) painter.drawPath(ribbon_path) # draw if favourited if gallery.fav == 1: star_ribbon_w = star_ribbon_l = w*0.08 rib_top_1 = QPointF(x+star_ribbon_l, y) rib_side_1 = QPointF(x, y+star_ribbon_l) rib_top_2 = QPointF(x+star_ribbon_l+star_ribbon_w, y) rib_side_2 = QPointF(x, y+star_ribbon_l+star_ribbon_w) rib_star_mid_1 = QPointF((rib_top_1.x()+rib_side_1.x())/2, (rib_top_1.y()+rib_side_1.y())/2) rib_star_factor = star_ribbon_l/4 rib_star_p1_1 = rib_star_mid_1 + QPointF(rib_star_factor, -rib_star_factor) rib_star_p1_2 = rib_star_p1_1 + QPointF(-rib_star_factor, -rib_star_factor) rib_star_p1_3 = rib_star_mid_1 + QPointF(-rib_star_factor, rib_star_factor) rib_star_p1_4 = rib_star_p1_3 + QPointF(-rib_star_factor, -rib_star_factor) crown_1 = QPolygonF([rib_star_p1_1, rib_star_p1_2, rib_star_mid_1, rib_star_p1_4, rib_star_p1_3]) painter.setBrush(QBrush(QColor("yellow"))) painter.drawPolygon(crown_1) ribbon_polygon = QPolygonF([rib_top_1, rib_side_1, rib_side_2, rib_top_2]) ribbon_path = QPainterPath() ribbon_path.setFillRule(Qt.WindingFill) ribbon_path.addPolygon(ribbon_polygon) ribbon_path.closeSubpath() painter.drawPath(ribbon_path) #painter.setPen(QColor("#d35400")) #painter.drawPolyline(rib_top_1, rib_star_p1_1, rib_star_p1_2, rib_star_mid_1, rib_star_p1_4, rib_star_p1_3, rib_side_1) #painter.drawLine(rib_top_1, rib_top_2) #painter.drawLine(rib_top_2, rib_side_2) #painter.drawLine(rib_side_1, rib_side_2) painter.restore() if app_constants._REFRESH_EXTERNAL_VIEWER: if app_constants.USE_EXTERNAL_VIEWER: self.external_icon = self.file_icons.get_external_file_icon() else: self.external_icon = self.file_icons.get_default_file_icon() if gallery.state == self.G_DOWNLOAD: painter.save() dl_box = QRect(x, y, w, 20) painter.setBrush(QBrush(QColor(0,0,0,123))) painter.setPen(QColor('white')) painter.drawRect(dl_box) painter.drawText(dl_box, Qt.AlignCenter, 'Downloading...') painter.restore() else: if app_constants.DISPLAY_GALLERY_TYPE: self.type_icon = self.file_icons.get_file_icon(gallery.path) if self.type_icon and not self.type_icon.isNull(): self.type_icon.paint(painter, QRect(x+2, y+app_constants.THUMB_H_SIZE-16, 16, 16)) if app_constants.USE_EXTERNAL_PROG_ICO: if self.external_icon and not self.external_icon.isNull(): self.external_icon.paint(painter, QRect(x+w-30, y+app_constants.THUMB_H_SIZE-28, 28, 28)) def draw_text_label(lbl_h): #draw the label for text painter.save() painter.translate(x, y+app_constants.THUMB_H_SIZE) box_color = QBrush(QColor(label_color))#QColor(0,0,0,123)) painter.setBrush(box_color) rect = QRect(0, 0, w, lbl_h) #x, y, width, height painter.fillRect(rect, box_color) painter.restore() return rect if option.state & QStyle.State_MouseOver or\ option.state & QStyle.State_Selected: title_layout = misc.text_layout(title, w, self.title_font, self.title_font_m) artist_layout = misc.text_layout(artist, w, self.artist_font, self.artist_font_m) t_h = title_layout.boundingRect().height() a_h = artist_layout.boundingRect().height() if app_constants.GALLERY_FONT_ELIDE: lbl_rect = draw_text_label(min(t_h+a_h+3, app_constants.GRIDBOX_LBL_H)) else: lbl_rect = draw_text_label(app_constants.GRIDBOX_LBL_H) clipping = QRectF(x, y+app_constants.THUMB_H_SIZE, w, app_constants.GRIDBOX_LBL_H - 10) painter.setPen(QColor(title_color)) title_layout.draw(painter, QPointF(x, y+app_constants.THUMB_H_SIZE), clip=clipping) painter.setPen(QColor(artist_color)) artist_layout.draw(painter, QPointF(x, y+app_constants.THUMB_H_SIZE+t_h), clip=clipping) #painter.fillRect(option.rect, QColor) else: if app_constants.GALLERY_FONT_ELIDE: lbl_rect = draw_text_label(self.text_label_h) else: lbl_rect = draw_text_label(app_constants.GRIDBOX_LBL_H) # draw text painter.save() alignment = QTextOption(Qt.AlignCenter) alignment.setUseDesignMetrics(True) title_rect = QRectF(0,0,w, self.title_font_m.height()) artist_rect = QRectF(0,self.artist_font_m.height(),w, self.artist_font_m.height()) painter.translate(x, y+app_constants.THUMB_H_SIZE) if app_constants.GALLERY_FONT_ELIDE: painter.setFont(self.title_font) painter.setPen(QColor(title_color)) painter.drawText(title_rect, self.title_font_m.elidedText(title, Qt.ElideRight, w-10), alignment) painter.setPen(QColor(artist_color)) painter.setFont(self.artist_font) alignment.setWrapMode(QTextOption.NoWrap) painter.drawText(artist_rect, self.title_font_m.elidedText(artist, Qt.ElideRight, w-10), alignment) else: text_area.setDefaultFont(QFont(self.font_name)) text_area.drawContents(painter) ##painter.resetTransform() painter.restore() if option.state & QStyle.State_Selected: painter.save() selected_rect = QRectF(x, y, w, lbl_rect.height()+app_constants.THUMB_H_SIZE) painter.setPen(Qt.NoPen) painter.setBrush(QBrush(QColor(164,164,164,120))) painter.drawRoundedRect(selected_rect, 5, 5) #painter.fillRect(selected_rect, QColor(164,164,164,120)) painter.restore() if gallery.dead_link: painter.save() selected_rect = QRectF(x, y, w, lbl_rect.height()+app_constants.THUMB_H_SIZE) painter.setPen(Qt.NoPen) painter.setBrush(QBrush(QColor(255,0,0,120))) p_path = QPainterPath() p_path.setFillRule(Qt.WindingFill) p_path.addRoundedRect(selected_rect, 5,5) p_path.addRect(x,y, 20, 20) p_path.addRect(x+w-20,y, 20, 20) painter.drawPath(p_path.simplified()) painter.setPen(QColor("white")) txt_layout = misc.text_layout("Cannot find gallery source!", w, self.title_font, self.title_font_m) txt_layout.draw(painter, QPointF(x, y+h*0.3)) painter.restore() if app_constants.DEBUG: painter.save() painter.setBrush(QBrush(QColor("red"))) painter.setPen(QColor("white")) txt_l = self.title_font_m.width(str(gallery.id)) painter.drawRect(x, y+40, txt_l*2, self.title_font_m.height()) painter.drawText(x+1, y+51, str(gallery.id)) painter.restore() if option.state & QStyle.State_Selected: painter.setPen(QPen(option.palette.highlightedText().color())) else: super().paint(painter, option, index)
def sizeHint(self, option, index): fm = option.fontMetrics document = QTextDocument() document.setDefaultFont(option.font) document.setHtml(index.model().data(index, Qt.DisplayRole)) return QSize(document.idealWidth() + 20, fm.height())
def CreatePDF(self, out, timestamp, data, frame, rows, columns, fileName, VManager): ''' Create PDF QgsTask ''' QCoreApplication.processEvents() QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) font_normal = QFont("Helvetica", 10, QFont.Normal) font_bold = QFont("Helvetica", 12, QFont.Bold) printer = QPrinter(QPrinter.HighResolution) printer.setOrientation(QPrinter.Portrait) printer.setOutputFormat(QPrinter.PdfFormat) printer.setFullPage(True) printer.setPaperSize(QPrinter.A4) printer.setOutputFileName(out) printer.setPageMargins(15, 15, 15, 15, QPrinter.Point) printer.setColorMode(QPrinter.Color) document = QTextDocument() document.setDefaultFont(font_normal) cursor = QTextCursor(document) cursor.movePosition(QTextCursor.Start, QTextCursor.MoveAnchor) cursor.insertHtml(""" <p style='text-align: center;'> <img style='display: block; margin-left: auto; margin-right: auto;' src=\':/imgFMV/images/header_logo.png\' width='200' height='25' /> </p> <p style='text-align: center;'> <strong>Video : </strong>%s<strong> </p> <p style='text-align: center;'> <strong>TimeStamp : </strong>%s</p><br><br> """ % (fileName, timestamp)) tableFormat = QTextTableFormat() tableFormat.setHeaderRowCount(1) tableFormat.setBorderBrush(QBrush(Qt.black)) tableFormat.setAlignment(Qt.AlignHCenter) tableFormat.setCellPadding(2) tableFormat.setCellSpacing(2) centerFormat = QTextBlockFormat() centerFormat.setAlignment(Qt.AlignCenter) cursor.insertBlock(centerFormat) textTable = cursor.insertTable(rows + 1, columns, tableFormat) tableHeaderFormat = QTextCharFormat() tableHeaderFormat.setFont(font_bold) tableHeaderFormat.setBackground(QColor("#67b03a")) tableHeaderFormat.setForeground(Qt.white) alternate_background = QTextCharFormat() alternate_background.setBackground(QColor("#DDE9ED")) for column in range(columns): cell = textTable.cellAt(0, column) cell.setFormat(tableHeaderFormat) cellCursor = cell.firstCursorPosition() cellCursor.insertText(VManager.horizontalHeaderItem(column).text()) row = 0 for key in sorted(data.keys()): cell0 = textTable.cellAt(row + 1, 0) cell1 = textTable.cellAt(row + 1, 1) cell2 = textTable.cellAt(row + 1, 2) if (row + 1) % 2 == 0: cell0.setFormat(alternate_background) cell1.setFormat(alternate_background) cell2.setFormat(alternate_background) cellCursor0 = cell0.firstCursorPosition() cellCursor0.insertText(str(key)) cellCursor1 = cell1.firstCursorPosition() cellCursor1.insertText(str(data[key][0])) cellCursor2 = cell2.firstCursorPosition() cellCursor2.insertText(str(data[key][1])) row += 1 cursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor) cursor.insertHtml(""" <br><p style='text-align: center;'><strong>Current Frame</strong></p><br> """) centerFormat = QTextBlockFormat() centerFormat.setAlignment(Qt.AlignHCenter) cursor.insertBlock(centerFormat) cursor.insertImage(frame.scaledToWidth(500)) QCoreApplication.processEvents() document.print_(printer) QCoreApplication.processEvents()
class CompletionItemDelegate(QStyledItemDelegate): """Delegate used by CompletionView to draw individual items. Mainly a cleaned up port of Qt's way to draw a TreeView item, except it uses a QTextDocument to draw the text and add marking. Original implementation: qt/src/gui/styles/qcommonstyle.cpp:drawControl:2153 Attributes: _opt: The QStyleOptionViewItem which is used. _style: The style to be used. _painter: The QPainter to be used. _doc: The QTextDocument to be used. """ # FIXME this is horribly slow when resizing. # We should probably cache something in _get_textdoc or so, but as soon as # we implement eliding that cache probably isn't worth much anymore... # https://github.com/qutebrowser/qutebrowser/issues/121 def __init__(self, parent=None): self._painter = None self._opt = None self._doc = None self._style = None super().__init__(parent) def _draw_background(self): """Draw the background of an ItemViewItem.""" self._style.drawPrimitive(self._style.PE_PanelItemViewItem, self._opt, self._painter, self._opt.widget) def _draw_icon(self): """Draw the icon of an ItemViewItem.""" icon_rect = self._style.subElementRect( self._style.SE_ItemViewItemDecoration, self._opt, self._opt.widget) if not icon_rect.isValid(): # The rect seems to be wrong in all kind of ways if no icon should # be displayed. return mode = QIcon.Normal if not self._opt.state & QStyle.State_Enabled: mode = QIcon.Disabled elif self._opt.state & QStyle.State_Selected: mode = QIcon.Selected state = QIcon.On if self._opt.state & QStyle.State_Open else QIcon.Off self._opt.icon.paint(self._painter, icon_rect, self._opt.decorationAlignment, mode, state) def _draw_text(self, index): """Draw the text of an ItemViewItem. This is the main part where we differ from the original implementation in Qt: We use a QTextDocument to draw text. Args: index: The QModelIndex of the item to draw. """ if not self._opt.text: return text_rect_ = self._style.subElementRect( self._style.SE_ItemViewItemText, self._opt, self._opt.widget) qtutils.ensure_valid(text_rect_) margin = self._style.pixelMetric(QStyle.PM_FocusFrameHMargin, self._opt, self._opt.widget) + 1 # remove width padding text_rect = text_rect_.adjusted(margin, 0, -margin, 0) qtutils.ensure_valid(text_rect) # move text upwards a bit if index.parent().isValid(): text_rect.adjust(0, -1, 0, -1) else: text_rect.adjust(0, -2, 0, -2) self._painter.save() state = self._opt.state if state & QStyle.State_Enabled and state & QStyle.State_Active: cg = QPalette.Normal elif state & QStyle.State_Enabled: cg = QPalette.Inactive else: cg = QPalette.Disabled if state & QStyle.State_Selected: self._painter.setPen(self._opt.palette.color( cg, QPalette.HighlightedText)) # This is a dirty fix for the text jumping by one pixel for # whatever reason. text_rect.adjust(0, -1, 0, 0) else: self._painter.setPen(self._opt.palette.color(cg, QPalette.Text)) if state & QStyle.State_Editing: self._painter.setPen(self._opt.palette.color(cg, QPalette.Text)) self._painter.drawRect(text_rect_.adjusted(0, 0, -1, -1)) self._painter.translate(text_rect.left(), text_rect.top()) self._get_textdoc(index) self._draw_textdoc(text_rect, index.column()) self._painter.restore() def _draw_textdoc(self, rect, col): """Draw the QTextDocument of an item. Args: rect: The QRect to clip the drawing to. """ # We can't use drawContents because then the color would be ignored. clip = QRectF(0, 0, rect.width(), rect.height()) self._painter.save() if self._opt.state & QStyle.State_Selected: color = config.val.colors.completion.item.selected.fg elif not self._opt.state & QStyle.State_Enabled: color = config.val.colors.completion.category.fg else: colors = config.val.colors.completion.fg # if multiple colors are set, use different colors per column color = colors[col % len(colors)] self._painter.setPen(color) ctx = QAbstractTextDocumentLayout.PaintContext() ctx.palette.setColor(QPalette.Text, self._painter.pen().color()) if clip.isValid(): self._painter.setClipRect(clip) ctx.clip = clip self._doc.documentLayout().draw(self._painter, ctx) self._painter.restore() def _get_textdoc(self, index): """Create the QTextDocument of an item. Args: index: The QModelIndex of the item to draw. """ # FIXME we probably should do eliding here. See # qcommonstyle.cpp:viewItemDrawText # https://github.com/qutebrowser/qutebrowser/issues/118 text_option = QTextOption() if self._opt.features & QStyleOptionViewItem.WrapText: text_option.setWrapMode(QTextOption.WordWrap) else: text_option.setWrapMode(QTextOption.ManualWrap) text_option.setTextDirection(self._opt.direction) text_option.setAlignment(QStyle.visualAlignment( self._opt.direction, self._opt.displayAlignment)) if self._doc is not None: self._doc.deleteLater() self._doc = QTextDocument(self) self._doc.setDefaultFont(self._opt.font) self._doc.setDefaultTextOption(text_option) self._doc.setDocumentMargin(2) assert _cached_stylesheet is not None self._doc.setDefaultStyleSheet(_cached_stylesheet) if index.parent().isValid(): view = self.parent() pattern = view.pattern columns_to_filter = index.model().columns_to_filter(index) if index.column() in columns_to_filter and pattern: repl = r'<span class="highlight">\g<0></span>' pat = html.escape(re.escape(pattern)).replace(r'\ ', r'|') txt = html.escape(self._opt.text) text = re.sub(pat, repl, txt, flags=re.IGNORECASE) self._doc.setHtml(text) else: self._doc.setPlainText(self._opt.text) else: self._doc.setHtml( '<span style="font: {};">{}</span>'.format( html.escape(config.val.fonts.completion.category), html.escape(self._opt.text))) def _draw_focus_rect(self): """Draw the focus rectangle of an ItemViewItem.""" state = self._opt.state if not state & QStyle.State_HasFocus: return o = self._opt o.rect = self._style.subElementRect( self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget) o.state |= QStyle.State_KeyboardFocusChange | QStyle.State_Item qtutils.ensure_valid(o.rect) if state & QStyle.State_Enabled: cg = QPalette.Normal else: cg = QPalette.Disabled if state & QStyle.State_Selected: role = QPalette.Highlight else: role = QPalette.Window o.backgroundColor = self._opt.palette.color(cg, role) self._style.drawPrimitive(QStyle.PE_FrameFocusRect, o, self._painter, self._opt.widget) def sizeHint(self, option, index): """Override sizeHint of QStyledItemDelegate. Return the cell size based on the QTextDocument size, but might not work correctly yet. Args: option: const QStyleOptionViewItem & option index: const QModelIndex & index Return: A QSize with the recommended size. """ value = index.data(Qt.SizeHintRole) if value is not None: return value self._opt = QStyleOptionViewItem(option) self.initStyleOption(self._opt, index) self._style = self._opt.widget.style() self._get_textdoc(index) docsize = self._doc.size().toSize() size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt, docsize, self._opt.widget) qtutils.ensure_valid(size) return size + QSize(10, 3) def paint(self, painter, option, index): """Override the QStyledItemDelegate paint function. Args: painter: QPainter * painter option: const QStyleOptionViewItem & option index: const QModelIndex & index """ self._painter = painter self._painter.save() self._opt = QStyleOptionViewItem(option) self.initStyleOption(self._opt, index) self._style = self._opt.widget.style() self._draw_background() self._draw_icon() self._draw_text(index) self._draw_focus_rect() self._painter.restore()
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())
class CompletionItemDelegate(QStyledItemDelegate): """Delegate used by CompletionView to draw individual items. Mainly a cleaned up port of Qt's way to draw a TreeView item, except it uses a QTextDocument to draw the text and add marking. Original implementation: qt/src/gui/styles/qcommonstyle.cpp:drawControl:2153 Attributes: _opt: The QStyleOptionViewItem which is used. _style: The style to be used. _painter: The QPainter to be used. _doc: The QTextDocument to be used. """ # FIXME this is horribly slow when resizing. # We should probably cache something in _get_textdoc or so, but as soon as # we implement eliding that cache probably isn't worth much anymore... # https://github.com/qutebrowser/qutebrowser/issues/121 def __init__(self, parent=None): self._painter = None self._opt = None self._doc = None self._style = None super().__init__(parent) def _draw_background(self): """Draw the background of an ItemViewItem.""" self._style.drawPrimitive(self._style.PE_PanelItemViewItem, self._opt, self._painter, self._opt.widget) def _draw_icon(self): """Draw the icon of an ItemViewItem.""" icon_rect = self._style.subElementRect( self._style.SE_ItemViewItemDecoration, self._opt, self._opt.widget) if not icon_rect.isValid(): # The rect seems to be wrong in all kind of ways if no icon should # be displayed. return mode = QIcon.Normal if not self._opt.state & QStyle.State_Enabled: mode = QIcon.Disabled elif self._opt.state & QStyle.State_Selected: mode = QIcon.Selected state = QIcon.On if self._opt.state & QStyle.State_Open else QIcon.Off self._opt.icon.paint(self._painter, icon_rect, self._opt.decorationAlignment, mode, state) def _draw_text(self, index): """Draw the text of an ItemViewItem. This is the main part where we differ from the original implementation in Qt: We use a QTextDocument to draw text. Args: index: The QModelIndex of the item to draw. """ if not self._opt.text: return text_rect_ = self._style.subElementRect( self._style.SE_ItemViewItemText, self._opt, self._opt.widget) qtutils.ensure_valid(text_rect_) margin = self._style.pixelMetric(QStyle.PM_FocusFrameHMargin, self._opt, self._opt.widget) + 1 # remove width padding text_rect = text_rect_.adjusted(margin, 0, -margin, 0) qtutils.ensure_valid(text_rect) # move text upwards a bit if index.parent().isValid(): text_rect.adjust(0, -1, 0, -1) else: text_rect.adjust(0, -2, 0, -2) self._painter.save() state = self._opt.state if state & QStyle.State_Enabled and state & QStyle.State_Active: cg = QPalette.Normal elif state & QStyle.State_Enabled: cg = QPalette.Inactive else: cg = QPalette.Disabled if state & QStyle.State_Selected: self._painter.setPen(self._opt.palette.color( cg, QPalette.HighlightedText)) # This is a dirty fix for the text jumping by one pixel for # whatever reason. text_rect.adjust(0, -1, 0, 0) else: self._painter.setPen(self._opt.palette.color(cg, QPalette.Text)) if state & QStyle.State_Editing: self._painter.setPen(self._opt.palette.color(cg, QPalette.Text)) self._painter.drawRect(text_rect_.adjusted(0, 0, -1, -1)) self._painter.translate(text_rect.left(), text_rect.top()) self._get_textdoc(index) self._draw_textdoc(text_rect, index.column()) self._painter.restore() def _draw_textdoc(self, rect, col): """Draw the QTextDocument of an item. Args: rect: The QRect to clip the drawing to. """ # We can't use drawContents because then the color would be ignored. clip = QRectF(0, 0, rect.width(), rect.height()) self._painter.save() if self._opt.state & QStyle.State_Selected: color = config.val.colors.completion.item.selected.fg elif not self._opt.state & QStyle.State_Enabled: color = config.val.colors.completion.category.fg else: colors = config.val.colors.completion.fg # if multiple colors are set, use different colors per column color = colors[col % len(colors)] self._painter.setPen(color) ctx = QAbstractTextDocumentLayout.PaintContext() ctx.palette.setColor(QPalette.Text, self._painter.pen().color()) if clip.isValid(): self._painter.setClipRect(clip) ctx.clip = clip self._doc.documentLayout().draw(self._painter, ctx) self._painter.restore() def _get_textdoc(self, index): """Create the QTextDocument of an item. Args: index: The QModelIndex of the item to draw. """ # FIXME we probably should do eliding here. See # qcommonstyle.cpp:viewItemDrawText # https://github.com/qutebrowser/qutebrowser/issues/118 text_option = QTextOption() if self._opt.features & QStyleOptionViewItem.WrapText: text_option.setWrapMode(QTextOption.WordWrap) else: text_option.setWrapMode(QTextOption.ManualWrap) text_option.setTextDirection(self._opt.direction) text_option.setAlignment(QStyle.visualAlignment( self._opt.direction, self._opt.displayAlignment)) if self._doc is not None: self._doc.deleteLater() self._doc = QTextDocument(self) self._doc.setDefaultFont(self._opt.font) self._doc.setDefaultTextOption(text_option) self._doc.setDocumentMargin(2) if index.parent().isValid(): view = self.parent() pattern = view.pattern columns_to_filter = index.model().columns_to_filter(index) self._doc.setPlainText(self._opt.text) if index.column() in columns_to_filter and pattern: pat = re.escape(pattern).replace(r'\ ', r'|') _Highlighter(self._doc, pat, config.val.colors.completion.match.fg) else: self._doc.setHtml( '<span style="font: {};">{}</span>'.format( html.escape(config.val.fonts.completion.category), html.escape(self._opt.text))) def _draw_focus_rect(self): """Draw the focus rectangle of an ItemViewItem.""" state = self._opt.state if not state & QStyle.State_HasFocus: return o = self._opt o.rect = self._style.subElementRect( self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget) o.state |= QStyle.State_KeyboardFocusChange | QStyle.State_Item qtutils.ensure_valid(o.rect) if state & QStyle.State_Enabled: cg = QPalette.Normal else: cg = QPalette.Disabled if state & QStyle.State_Selected: role = QPalette.Highlight else: role = QPalette.Window o.backgroundColor = self._opt.palette.color(cg, role) self._style.drawPrimitive(QStyle.PE_FrameFocusRect, o, self._painter, self._opt.widget) def sizeHint(self, option, index): """Override sizeHint of QStyledItemDelegate. Return the cell size based on the QTextDocument size, but might not work correctly yet. Args: option: const QStyleOptionViewItem & option index: const QModelIndex & index Return: A QSize with the recommended size. """ value = index.data(Qt.SizeHintRole) if value is not None: return value self._opt = QStyleOptionViewItem(option) self.initStyleOption(self._opt, index) self._style = self._opt.widget.style() self._get_textdoc(index) docsize = self._doc.size().toSize() size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt, docsize, self._opt.widget) qtutils.ensure_valid(size) return size + QSize(10, 3) def paint(self, painter, option, index): """Override the QStyledItemDelegate paint function. Args: painter: QPainter * painter option: const QStyleOptionViewItem & option index: const QModelIndex & index """ self._painter = painter self._painter.save() self._opt = QStyleOptionViewItem(option) self.initStyleOption(self._opt, index) self._style = self._opt.widget.style() self._draw_background() self._draw_icon() self._draw_text(index) self._draw_focus_rect() self._painter.restore()
def paint(self, painter, option, index): dlg = index.model().data(index, Qt.DisplayRole) painter.setRenderHint(QPainter.Antialiasing) color = QColor(Qt.white) if option.state & QStyle.State_MouseOver: color = QColor(variables.HIGHLIGHT_COLOR) painter.setPen(QPen(color)) painter.setBrush(QBrush(color)) painter.drawRect(option.rect) painter.setPen(Qt.black) painter.setBrush(Qt.NoBrush) painter.drawLine(option.rect.bottomLeft(), option.rect.bottomRight()) doc = QTextDocument(dlg.ip) doc.setDocumentMargin(0) doc.setDefaultFont(variables.font) textrect = QRect(option.rect) textrect = textrect.marginsRemoved(variables.IP_PADDING) textrect.setHeight(int(doc.size().height())) textrect.setWidth(int(doc.size().width())) offset = textrect.marginsAdded(variables.IP_PADDING).height() painter.setPen(Qt.black) painter.setFont(variables.font) painter.translate(textrect.x(), textrect.y()) textrectf = QRectF(textrect) textrectf.moveTo(0, 0) doc.drawContents(painter, textrectf) painter.translate(-textrect.x(), -textrect.y()) string = "" if dlg.user == variables.USER_ME: string += "You: " print(dlg.msg) string += dlg.msg fm = QFontMetrics(variables.font_small) textrect = QRect(option.rect) textrect.moveTop(textrect.y() + offset) textrect = textrect.marginsRemoved(variables.MSG_PADDING) textrect.setHeight(fm.lineSpacing()) spainter = QStylePainter(painter.device(), QWidget()) spainter.setRenderHint(QPainter.Antialiasing) if fm.horizontalAdvance(string) > textrect.width(): fade = QLinearGradient(variables.MSG_PADDING.left() + textrect.width()* 0.9, 0, variables.MSG_PADDING.left() + textrect.width(), 0) fade.setSpread(QGradient.PadSpread) fade.setColorAt(0, Qt.darkGray) fade.setColorAt(1, color) pal = QPalette() pal.setBrush(QPalette.Text, QBrush(fade)) spainter.setFont(variables.font_small) spainter.drawItemText(textrect, Qt.TextSingleLine, pal, True, string, QPalette.Text) else: spainter.setPen(Qt.darkGray) spainter.setFont(variables.font_small) spainter.drawText(textrect, Qt.TextSingleLine, string) p1 = textrect.bottomRight() + QPoint(36, -int(textrect.height() / 2)) if dlg.status == variables.STATUS_UNREAD: spainter.setPen(Qt.NoPen) spainter.setBrush(QColor(variables.STATUS_COLOR)) spainter.drawEllipse(p1, 7, 7) elif dlg.status == variables.STATUS_UNDELIVERED: pen = QPen(QColor(variables.STATUS_COLOR)) pen.setWidth(2) spainter.setPen(pen) spainter.setBrush(Qt.NoBrush) spainter.drawEllipse(p1, 7, 7) spainter.drawLine(p1, p1 + QPoint(0, -5)) spainter.drawLine(p1, p1 + QPoint(3, 0)) elif dlg.status == variables.STATUS_NEW: pen = QPen(QColor(variables.STATUS_NEW_COLOR)) pen.setWidth(5) spainter.setPen(pen) spainter.setBrush(Qt.NoBrush) spainter.drawEllipse(p1, 7, 7) #painter.translate(-textrect.x(), -textrect.y()) '''doc = QTextDocument(str)