def paint(self, painter, option, index): QStyledItemDelegate.paint(self, painter, option, index) text, positions = index.data(Qt.UserRole).toPyObject() 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 __init__(self, parent=None): QWidget.__init__(self, parent=parent) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.results = () self.current_result = -1 self.max_result = -1 self.mouse_hover_result = -1 self.setMouseTracking(True) self.setFocusPolicy(Qt.NoFocus) self.text_option = to = QTextOption() to.setWrapMode(to.NoWrap) self.divider = QStaticText('\xa0→ \xa0') self.divider.setTextFormat(Qt.PlainText)
def __init__( self, file_object, page_width, page_height, left_margin, top_margin, right_margin, bottom_margin, width, height, errors=print, debug=print, compress=True, ): QPaintEngine.__init__(self, self.features) self.file_object = file_object self.compress = compress self.page_height, self.page_width = page_height, page_width self.left_margin, self.top_margin = left_margin, top_margin self.right_margin, self.bottom_margin = right_margin, bottom_margin self.pixel_width, self.pixel_height = width, height # Setup a co-ordinate transform that allows us to use co-ords # from Qt's pixel based co-ordinate system with its origin at the top # left corner. PDF's co-ordinate system is based on pts and has its # origin in the bottom left corner. We also have to implement the page # margins. Therefore, we need to translate, scale and reflect about the # x-axis. dy = self.page_height - self.top_margin dx = self.left_margin sx = (self.page_width - self.left_margin - self.right_margin) / self.pixel_width sy = (self.page_height - self.top_margin - self.bottom_margin) / self.pixel_height self.pdf_system = QTransform(sx, 0, 0, -sy, dx, dy) self.do_stroke = True self.do_fill = False self.scale = sqrt(sy ** 2 + sx ** 2) self.xscale, self.yscale = sx, sy self.graphics_state = GraphicsState() self.errors_occurred = False self.errors, self.debug = errors, debug self.text_option = QTextOption() self.text_option.setWrapMode(QTextOption.NoWrap) self.fonts = {} i = QImage(1, 1, QImage.Format_ARGB32) i.fill(qRgba(0, 0, 0, 255)) self.alpha_bit = i.constBits().asstring(4).find(b"\xff") self.current_page_num = 1 self.current_page_inited = False
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 = ''
class PdfEngine(QPaintEngine): def __init__( self, file_object, page_width, page_height, left_margin, top_margin, right_margin, bottom_margin, width, height, errors=print, debug=print, compress=True, ): QPaintEngine.__init__(self, self.features) self.file_object = file_object self.compress = compress self.page_height, self.page_width = page_height, page_width self.left_margin, self.top_margin = left_margin, top_margin self.right_margin, self.bottom_margin = right_margin, bottom_margin self.pixel_width, self.pixel_height = width, height # Setup a co-ordinate transform that allows us to use co-ords # from Qt's pixel based co-ordinate system with its origin at the top # left corner. PDF's co-ordinate system is based on pts and has its # origin in the bottom left corner. We also have to implement the page # margins. Therefore, we need to translate, scale and reflect about the # x-axis. dy = self.page_height - self.top_margin dx = self.left_margin sx = (self.page_width - self.left_margin - self.right_margin) / self.pixel_width sy = (self.page_height - self.top_margin - self.bottom_margin) / self.pixel_height self.pdf_system = QTransform(sx, 0, 0, -sy, dx, dy) self.do_stroke = True self.do_fill = False self.scale = sqrt(sy ** 2 + sx ** 2) self.xscale, self.yscale = sx, sy self.graphics_state = GraphicsState() self.errors_occurred = False self.errors, self.debug = errors, debug self.text_option = QTextOption() self.text_option.setWrapMode(QTextOption.NoWrap) self.fonts = {} i = QImage(1, 1, QImage.Format_ARGB32) i.fill(qRgba(0, 0, 0, 255)) self.alpha_bit = i.constBits().asstring(4).find(b"\xff") self.current_page_num = 1 self.current_page_inited = False def init_page(self): self.pdf.transform(self.pdf_system) self.pdf.set_rgb_colorspace() width = self.painter().pen().widthF() if self.isActive() else 0 self.pdf.set_line_width(width) self.do_stroke = True self.do_fill = False self.graphics_state.reset() self.pdf.save_stack() self.current_page_inited = True @property def features(self): return ( QPaintEngine.Antialiasing | QPaintEngine.AlphaBlend | QPaintEngine.ConstantOpacity | QPaintEngine.PainterPaths | QPaintEngine.PaintOutsidePaintEvent | QPaintEngine.PrimitiveTransform ) def begin(self, device): if not hasattr(self, "pdf"): try: self.pdf = PDFStream(self.file_object, (self.page_width, self.page_height), compress=self.compress) except: self.errors.append(traceback.format_exc()) return False return True def end_page(self): if self.current_page_inited: self.pdf.restore_stack() self.pdf.end_page() self.current_page_inited = False self.current_page_num += 1 def end(self): try: self.end_page() self.pdf.end() except: self.errors.append(traceback.format_exc()) return False finally: self.pdf = self.file_object = None return True def type(self): return QPaintEngine.Pdf @store_error def drawPixmap(self, rect, pixmap, source_rect): self.graphics_state(self) source_rect = source_rect.toRect() pixmap = pixmap if source_rect == pixmap.rect() else pixmap.copy(source_rect) image = pixmap.toImage() ref = self.add_image(image, pixmap.cacheKey()) if ref is not None: self.pdf.draw_image(rect.x(), rect.height() + rect.y(), rect.width(), -rect.height(), ref) @store_error def drawImage(self, rect, image, source_rect, flags=Qt.AutoColor): self.graphics_state(self) source_rect = source_rect.toRect() image = image if source_rect == image.rect() else image.copy(source_rect) ref = self.add_image(image, image.cacheKey()) if ref is not None: self.pdf.draw_image(rect.x(), rect.height() + rect.y(), rect.width(), -rect.height(), ref) def add_image(self, img, cache_key): if img.isNull(): return ref = self.pdf.get_image(cache_key) if ref is not None: return ref fmt = img.format() image = QImage(img) if ( image.depth() == 1 and img.colorTable().size() == 2 and img.colorTable().at(0) == QColor(Qt.black).rgba() and img.colorTable().at(1) == QColor(Qt.white).rgba() ): if fmt == QImage.Format_MonoLSB: image = image.convertToFormat(QImage.Format_Mono) fmt = QImage.Format_Mono else: if fmt != QImage.Format_RGB32 and fmt != QImage.Format_ARGB32: image = image.convertToFormat(QImage.Format_ARGB32) fmt = QImage.Format_ARGB32 w = image.width() h = image.height() d = image.depth() if fmt == QImage.Format_Mono: bytes_per_line = (w + 7) >> 3 data = image.constBits().asstring(bytes_per_line * h) return self.pdf.write_image(data, w, h, d, cache_key=cache_key) ba = QByteArray() buf = QBuffer(ba) image.save(buf, "jpeg", 94) data = bytes(ba.data()) has_alpha = has_mask = False soft_mask = mask = None if fmt == QImage.Format_ARGB32: tmask = image.constBits().asstring(4 * w * h)[self.alpha_bit :: 4] sdata = bytearray(tmask) vals = set(sdata) vals.discard(255) has_mask = bool(vals) vals.discard(0) has_alpha = bool(vals) if has_alpha: soft_mask = self.pdf.write_image(tmask, w, h, 8) elif has_mask: # dither the soft mask to 1bit and add it. This also helps PDF # viewers without transparency support bytes_per_line = (w + 7) >> 3 mdata = bytearray(0 for i in xrange(bytes_per_line * h)) spos = mpos = 0 for y in xrange(h): for x in xrange(w): if sdata[spos]: mdata[mpos + x >> 3] |= 0x80 >> (x & 7) spos += 1 mpos += bytes_per_line mdata = bytes(mdata) mask = self.pdf.write_image(mdata, w, h, 1) return self.pdf.write_image(data, w, h, 32, mask=mask, dct=True, soft_mask=soft_mask, cache_key=cache_key) @store_error def updateState(self, state): self.graphics_state.read(state) def convert_path(self, path): p = Path() i = 0 while i < path.elementCount(): elem = path.elementAt(i) em = (elem.x, elem.y) i += 1 if elem.isMoveTo(): p.move_to(*em) elif elem.isLineTo(): p.line_to(*em) elif elem.isCurveTo(): added = False if path.elementCount() > i + 1: c1, c2 = path.elementAt(i), path.elementAt(i + 1) if c1.type == path.CurveToDataElement and c2.type == path.CurveToDataElement: i += 2 p.curve_to(em[0], em[1], c1.x, c1.y, c2.x, c2.y) added = True if not added: raise ValueError("Invalid curve to operation") return p @store_error def drawPath(self, path): self.graphics_state(self) p = self.convert_path(path) fill_rule = {Qt.OddEvenFill: "evenodd", Qt.WindingFill: "winding"}[path.fillRule()] self.pdf.draw_path(p, stroke=self.do_stroke, fill=self.do_fill, fill_rule=fill_rule) def add_clip(self, path): p = self.convert_path(path) fill_rule = {Qt.OddEvenFill: "evenodd", Qt.WindingFill: "winding"}[path.fillRule()] self.pdf.add_clip(p, fill_rule=fill_rule) @store_error def drawPoints(self, points): self.graphics_state(self) p = Path() for point in points: p.move_to(point.x(), point.y()) p.line_to(point.x(), point.y() + 0.001) self.pdf.draw_path(p, stroke=self.do_stroke, fill=False) @store_error def drawRects(self, rects): self.graphics_state(self) for rect in rects: bl = rect.topLeft() self.pdf.draw_rect(bl.x(), bl.y(), rect.width(), rect.height(), stroke=self.do_stroke, fill=self.do_fill) def get_text_layout(self, text_item, text): tl = QTextLayout(text, text_item.font(), self.paintDevice()) self.text_option.setTextDirection( Qt.RightToLeft if text_item.renderFlags() & text_item.RightToLeft else Qt.LeftToRight ) tl.setTextOption(self.text_option) return tl def update_glyph_map(self, text, indices, text_item, glyph_map): """ Map glyphs back to the unicode text they represent. """ pos = 0 tl = self.get_text_layout(text_item, "") indices = list(indices) def get_glyphs(string): tl.setText(string) tl.beginLayout() line = tl.createLine() if not line.isValid(): tl.endLayout() return [] line.setLineWidth(int(1e12)) tl.endLayout() ans = [] for run in tl.glyphRuns(): ans.extend(run.glyphIndexes()) return ans ipos = 0 while ipos < len(indices): if indices[ipos] in glyph_map: t = glyph_map[indices[ipos]] if t == text[pos : pos + len(t)]: pos += len(t) ipos += 1 continue found = False for l in xrange(1, 10): string = text[pos : pos + l] g = get_glyphs(string) if g and g[0] == indices[ipos]: found = True glyph_map[g[0]] = string break if not found: self.debug("Failed to find glyph->unicode mapping for text: %s" % text) break ipos += 1 pos += l return text[pos:] @store_error def drawTextItem(self, point, text_item): # super(PdfEngine, self).drawTextItem(point, text_item) self.graphics_state(self) text = type("")(text_item.text()).replace("\n", " ") text = unicodedata.normalize("NFKC", text) tl = self.get_text_layout(text_item, text) tl.setPosition(point) tl.beginLayout() line = tl.createLine() if not line.isValid(): tl.endLayout() return line.setLineWidth(int(1e12)) tl.endLayout() for run in tl.glyphRuns(): rf = run.rawFont() name = hash(bytes(rf.fontTable("name"))) if name not in self.fonts: self.fonts[name] = Font(Sfnt(rf)) metrics = self.fonts[name] indices = run.glyphIndexes() text = self.update_glyph_map(text, indices, text_item, metrics.glyph_map) glyphs = [] pdf_pos = point first_baseline = None for i, pos in enumerate(run.positions()): if first_baseline is None: first_baseline = pos.y() glyph_pos = point + pos delta = glyph_pos - pdf_pos glyphs.append((delta.x(), pos.y() - first_baseline, indices[i])) pdf_pos = glyph_pos self.pdf.draw_glyph_run([1, 0, 0, -1, point.x(), point.y()], rf.pixelSize(), metrics, glyphs) @store_error def drawPolygon(self, points, mode): self.graphics_state(self) if not points: return p = Path() p.move_to(points[0].x(), points[0].y()) for point in points[1:]: p.line_to(point.x(), point.y()) p.close() fill_rule = {self.OddEvenMode: "evenodd", self.WindingMode: "winding"}.get(mode, "evenodd") self.pdf.draw_path( p, stroke=True, fill_rule=fill_rule, fill=(mode in (self.OddEvenMode, self.WindingMode, self.ConvexMode)) ) def set_metadata(self, *args, **kwargs): self.pdf.set_metadata(*args, **kwargs) def __enter__(self): self.pdf.save_stack() self.saved_ps = (self.do_stroke, self.do_fill) def __exit__(self, *args): self.do_stroke, self.do_fill = self.saved_ps self.pdf.restore_stack()