def __init__(self, stream, page_size, compress=False, mark_links=False, debug=print): self.stream = HashingStream(stream) self.compress = compress self.write_line(PDFVER) self.write_line('%íì¦"'.encode()) creator = ('%s %s [https://calibre-ebook.com]'%(__appname__, __version__)) self.write_line('%% Created by %s'%creator) self.objects = IndirectObjects() self.objects.add(PageTree(page_size)) self.objects.add(Catalog(self.page_tree)) self.current_page = Page(self.page_tree, compress=self.compress) self.info = Dictionary({ 'Creator':String(creator), 'Producer':String(creator), 'CreationDate': utcnow(), }) self.stroke_opacities, self.fill_opacities = {}, {} self.font_manager = FontManager(self.objects, self.compress) self.image_cache = {} self.pattern_cache, self.shader_cache = {}, {} self.debug = debug self.page_size = page_size self.links = Links(self, mark_links, page_size) i = QImage(1, 1, QImage.Format.Format_ARGB32) i.fill(qRgba(0, 0, 0, 255)) self.alpha_bit = i.constBits().asstring(4).find(b'\xff') self.bw_image_color_table = frozenset((QColor(Qt.GlobalColor.black).rgba(), QColor(Qt.GlobalColor.white).rgba()))
def paintEvent(self, event): pmap = self.blank if self.pixmap is None or self.pixmap.isNull( ) else self.pixmap target = self.rect() scaled, width, height = fit_image(pmap.width(), pmap.height(), target.width(), target.height()) target.setRect(target.x(), target.y(), width, height) p = QPainter(self) p.setRenderHints(QPainter.RenderHint.Antialiasing | QPainter.RenderHint.SmoothPixmapTransform) p.drawPixmap(target, pmap) if self.pixmap is not None and not self.pixmap.isNull(): sztgt = target.adjusted(0, 0, 0, -4) f = p.font() f.setBold(True) p.setFont(f) sz = u'\u00a0%d x %d\u00a0' % (self.pixmap.width(), self.pixmap.height()) flags = int(Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight | Qt.TextFlag.TextSingleLine) szrect = p.boundingRect(sztgt, flags, sz) p.fillRect(szrect.adjusted(0, 0, 0, 4), QColor(0, 0, 0, 200)) p.setPen(QPen(QColor(255, 255, 255))) p.drawText(sztgt, flags, sz) p.end()
def drag_icon(self, cover, multiple): cover = cover.scaledToHeight(120, Qt.TransformationMode.SmoothTransformation) if multiple: base_width = cover.width() base_height = cover.height() base = QImage(base_width+21, base_height+21, QImage.Format.Format_ARGB32_Premultiplied) base.fill(QColor(255, 255, 255, 0).rgba()) p = QPainter(base) rect = QRect(20, 0, base_width, base_height) p.fillRect(rect, QColor('white')) p.drawRect(rect) rect.moveLeft(10) rect.moveTop(10) p.fillRect(rect, QColor('white')) p.drawRect(rect) rect.moveLeft(0) rect.moveTop(20) p.fillRect(rect, QColor('white')) p.save() p.setCompositionMode(QPainter.CompositionMode.CompositionMode_SourceAtop) p.drawImage(rect.topLeft(), cover) p.restore() p.drawRect(rect) p.end() cover = base return QPixmap.fromImage(cover)
def create_icon(text, palette=None, sz=None, divider=2, fill='white'): if isinstance(fill, string_or_bytes): fill = QColor(fill) sz = sz or int( math.ceil(tprefs['toolbar_icon_size'] * QApplication.instance().devicePixelRatio())) if palette is None: palette = QApplication.palette() img = QImage(sz, sz, QImage.Format.Format_ARGB32) img.fill(Qt.GlobalColor.transparent) p = QPainter(img) p.setRenderHints(QPainter.RenderHint.TextAntialiasing | QPainter.RenderHint.Antialiasing) if fill is not None: qDrawShadeRect(p, img.rect(), palette, fill=fill, lineWidth=1, midLineWidth=1) f = p.font() f.setFamily('Liberation Sans'), f.setPixelSize(int( sz // divider)), f.setBold(True) p.setFont(f), p.setPen(QColor('#2271d5')) p.drawText(img.rect().adjusted(2, 2, -2, -2), Qt.AlignmentFlag.AlignCenter, text) p.end() return QIcon(QPixmap.fromImage(img))
def __init__(self, color, parent=None): QToolButton.__init__(self, parent) self.setIconSize(QSize(50, 25)) self.pix = QPixmap(self.iconSize()) self._color = QColor('#' + color) self.pix.fill(self._color) self.setIcon(QIcon(self.pix)) self.clicked.connect(self.choose_color)
def add_image(self, img, cache_key): ref = self.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.GlobalColor.black).rgba() and img.colorTable().at(1) == QColor(Qt.GlobalColor.white).rgba()): if fmt == QImage.Format.Format_MonoLSB: image = image.convertToFormat(QImage.Format.Format_Mono) fmt = QImage.Format.Format_Mono else: if (fmt != QImage.Format.Format_RGB32 and fmt != QImage.Format.Format_ARGB32): image = image.convertToFormat(QImage.Format.Format_ARGB32) fmt = QImage.Format.Format_ARGB32 w = image.width() h = image.height() d = image.depth() if fmt == QImage.Format.Format_Mono: bytes_per_line = (w + 7) >> 3 data = image.constBits().asstring(bytes_per_line * h) return self.write_image(data, w, h, d, cache_key=cache_key) has_alpha = False soft_mask = None if fmt == QImage.Format.Format_ARGB32: tmask = image.constBits().asstring(4*w*h)[self.alpha_bit::4] sdata = bytearray(tmask) vals = set(sdata) vals.discard(255) # discard opaque pixels has_alpha = bool(vals) if has_alpha: # Blend image onto a white background as otherwise Qt will render # transparent pixels as black background = QImage(image.size(), QImage.Format.Format_ARGB32_Premultiplied) background.fill(Qt.GlobalColor.white) painter = QPainter(background) painter.drawImage(0, 0, image) painter.end() image = background ba = QByteArray() buf = QBuffer(ba) image.save(buf, 'jpeg', 94) data = ba.data() if has_alpha: soft_mask = self.write_image(tmask, w, h, 8) return self.write_image(data, w, h, 32, dct=True, soft_mask=soft_mask, cache_key=cache_key)
def draw_size(p, rect, w, h): rect = rect.adjusted(0, 0, 0, -4) f = p.font() f.setBold(True) p.setFont(f) sz = '\u00a0%d x %d\u00a0' % (w, h) flags = Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight | Qt.TextFlag.TextSingleLine szrect = p.boundingRect(rect, flags, sz) p.fillRect(szrect.adjusted(0, 0, 0, 4), QColor(0, 0, 0, 200)) p.setPen(QPen(QColor(255, 255, 255))) p.drawText(rect, flags, sz)
def read_color(col): if QColor.isValidColor(col): return QBrush(QColor(col)) if col.startswith('rgb('): r, g, b = map(int, (x.strip() for x in col[4:-1].split(','))) return QBrush(QColor(r, g, b)) try: r, g, b = col[0:2], col[2:4], col[4:6] r, g, b = int(r, 16), int(g, 16), int(b, 16) return QBrush(QColor(r, g, b)) except Exception: pass
def draw_image_error(self, painter): font = painter.font() font.setPointSize(3 * font.pointSize()) font.setBold(True) painter.setFont(font) painter.setPen(QColor(Qt.GlobalColor.black)) painter.drawText(self.rect(), Qt.AlignmentFlag.AlignCenter, _('Not a valid image'))
def __init__(self, right=False, parent=None, show_open_in_editor=False): PlainTextEdit.__init__(self, parent) self.setFrameStyle(0) self.show_open_in_editor = show_open_in_editor self.side_margin = 0 self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.customContextMenuRequested.connect(self.show_context_menu) self.setFocusPolicy(Qt.FocusPolicy.NoFocus) self.right = right self.setReadOnly(True) self.setLineWrapMode(QPlainTextEdit.LineWrapMode.WidgetWidth) font = self.font() ff = tprefs['editor_font_family'] if ff is None: ff = default_font_family() font.setFamily(ff) font.setPointSize(tprefs['editor_font_size']) self.setFont(font) self.calculate_metrics() self.setTabStopWidth(tprefs['editor_tab_stop_width'] * self.space_width) font = self.heading_font = QFont(self.font()) font.setPointSize(int(tprefs['editor_font_size'] * 1.5)) font.setBold(True) theme = get_theme(tprefs['editor_theme']) pal = self.palette() pal.setColor(QPalette.ColorRole.Base, theme_color(theme, 'Normal', 'bg')) pal.setColor(QPalette.ColorRole.AlternateBase, theme_color(theme, 'CursorLine', 'bg')) pal.setColor(QPalette.ColorRole.Text, theme_color(theme, 'Normal', 'fg')) pal.setColor(QPalette.ColorRole.Highlight, theme_color(theme, 'Visual', 'bg')) pal.setColor(QPalette.ColorRole.HighlightedText, theme_color(theme, 'Visual', 'fg')) self.setPalette(pal) self.viewport().setCursor(Qt.CursorShape.ArrowCursor) self.line_number_area = LineNumbers(self) self.blockCountChanged[int].connect(self.update_line_number_area_width) self.updateRequest.connect(self.update_line_number_area) self.line_number_palette = pal = QPalette() pal.setColor(QPalette.ColorRole.Base, theme_color(theme, 'LineNr', 'bg')) pal.setColor(QPalette.ColorRole.Text, theme_color(theme, 'LineNr', 'fg')) pal.setColor(QPalette.ColorRole.BrightText, theme_color(theme, 'LineNrC', 'fg')) self.line_number_map = LineNumberMap() self.search_header_pos = 0 self.changes, self.headers, self.images = [], [], OrderedDict() self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff), self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.diff_backgrounds = { 'replace' : theme_color(theme, 'DiffReplace', 'bg'), 'insert' : theme_color(theme, 'DiffInsert', 'bg'), 'delete' : theme_color(theme, 'DiffDelete', 'bg'), 'replacereplace': theme_color(theme, 'DiffReplaceReplace', 'bg'), 'boundary': QBrush(theme_color(theme, 'Normal', 'fg'), Qt.BrushStyle.Dense7Pattern), } self.diff_foregrounds = { 'replace' : theme_color(theme, 'DiffReplace', 'fg'), 'insert' : theme_color(theme, 'DiffInsert', 'fg'), 'delete' : theme_color(theme, 'DiffDelete', 'fg'), 'boundary': QColor(0, 0, 0, 0), } for x in ('replacereplace', 'insert', 'delete'): f = QTextCharFormat() f.setBackground(self.diff_backgrounds[x]) setattr(self, '%s_format' % x, f)
def initializeFormats(self): Config = self.Config Config["fontfamily"] = "monospace" pal = QApplication.instance().palette() for name, color, bold, italic in ( ("normal", None, False, False), ("keyword", pal.color(QPalette.ColorRole.Link).name(), True, False), ("builtin", pal.color(QPalette.ColorRole.Link).name(), False, False), ("comment", "#007F00", False, True), ("string", "#808000", False, False), ("number", "#924900", False, False), ("lparen", None, True, True), ("rparen", None, True, True)): Config["%sfontcolor" % name] = color Config["%sfontbold" % name] = bold Config["%sfontitalic" % name] = italic baseFormat = QTextCharFormat() baseFormat.setFontFamily(Config["fontfamily"]) Config["fontsize"] = gprefs['gpm_template_editor_font_size'] baseFormat.setFontPointSize(Config["fontsize"]) for name in ("normal", "keyword", "builtin", "comment", "string", "number", "lparen", "rparen"): format = QTextCharFormat(baseFormat) col = Config["%sfontcolor" % name] if col: format.setForeground(QColor(col)) if Config["%sfontbold" % name]: format.setFontWeight(QFont.Weight.Bold) format.setFontItalic(Config["%sfontitalic" % name]) self.Formats[name] = format
def update_hover(self, hovering): cell = self.rows[0][0] if (hovering and cell.override_color is None) or ( not hovering and cell.override_color is not None): cell.override_color = QColor( Qt.GlobalColor.red) if hovering else None self.update()
def color(self, val): val = unicode_type(val or '') col = QColor(val) orig = self._color if col.isValid(): self._color = val self.setText(val) p = QPixmap(self.iconSize()) p.fill(col) self.setIcon(QIcon(p)) else: self._color = None self.setText(self.choose_text) self.setIcon(QIcon()) if orig != col: self.color_changed.emit(self._color)
def __init__(self, parent): QWidget.__init__(self, parent) self.bcol = QColor(*gprefs['cover_grid_color']) self.btex = gprefs['cover_grid_texture'] self.update_brush() self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
class ColorButton(QToolButton): def __init__(self, color, parent=None): QToolButton.__init__(self, parent) self.setIconSize(QSize(50, 25)) self.pix = QPixmap(self.iconSize()) self._color = QColor('#' + color) self.pix.fill(self._color) self.setIcon(QIcon(self.pix)) self.clicked.connect(self.choose_color) @property def color(self): return self._color.name(QColor.NameFormat.HexRgb)[1:] @color.setter def color(self, val): self._color = QColor('#' + val) def update_display(self): self.pix.fill(self._color) self.setIcon(QIcon(self.pix)) def choose_color(self): c = QColorDialog.getColor(self._color, self, _('Choose color')) if c.isValid(): self._color = c self.update_display()
def drawContents(self, painter): self.drawn_once = True painter.save() painter.setRenderHint(QPainter.RenderHint.TextAntialiasing, True) painter.setRenderHint(QPainter.RenderHint.Antialiasing, True) pw = self.LOGO_SIZE height = max(pw, self.total_height) width = self.width() # Draw frame y = (self.height() - height) // 2 bottom = y + height painter.fillRect(0, y, width, height, self.light_brush) painter.fillRect(0, y, width, self.title_height, self.dark_brush) painter.fillRect(0, y, pw, height, self.dark_brush) dy = (height - self.LOGO_SIZE) // 2 painter.drawPixmap(0, y + dy, self.pmap) # Draw number painter.setFont(self.num_font) num_width = painter.boundingRect( 0, 0, 0, 0, Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextSingleLine, self.num_ch).width() + 12 num_x = width - num_width painter.setPen(QPen(QColor('#d6b865'))) painter.drawText( num_x, y, num_width, height, Qt.AlignmentFlag.AlignCenter | Qt.TextFlag.TextSingleLine, self.num_ch) # Draw title x = pw + 10 width -= num_width + 5 + x painter.setFont(self.title_font) painter.drawText( x, y, width, self.title_height, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter | Qt.TextFlag.TextSingleLine, "CALIBRE") # Draw starting up message y += self.title_height + 5 painter.setPen(QPen(self.dark_brush.color())) painter.setFont(self.body_font) br = painter.drawText( x, y, width, self.line_height, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter | Qt.TextFlag.TextSingleLine, _('Starting up, please wait...')) starting_up_bottom = br.bottom() # Draw footer m = self.message() if m and m.strip(): painter.setFont(self.footer_font) b = max(starting_up_bottom + 5, bottom - self.line_height) painter.drawText( x, b, width, self.line_height, Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop | Qt.TextFlag.TextSingleLine, m) painter.restore()
def make_color_combobox(self, row, dex): c = QComboBox(self) c.addItem('') c.addItems(QColor.colorNames()) self.table.setCellWidget(row, 1, c) if dex >= 0: c.setCurrentIndex(dex) return c
def add_borders_to_image(img, left=0, top=0, right=0, bottom=0, border_color='#ffffff'): img = image_from_data(img) if not (left > 0 or right > 0 or top > 0 or bottom > 0): return img canvas = QImage(img.width() + left + right, img.height() + top + bottom, QImage.Format.Format_RGB32) canvas.fill(QColor(border_color)) overlay_image(img, canvas, left, top) return canvas
def __init__(self, text, rect, right_align=False, color_role=QPalette.ColorRole.WindowText, swatch=None, is_overriden=False): self.rect, self.text = rect, text self.right_align = right_align self.is_overriden = is_overriden self.color_role = color_role self.override_color = None self.swatch = swatch if swatch is not None: self.swatch = QColor(swatch[0], swatch[1], swatch[2], int(255 * swatch[3]))
def blend_on_canvas(img, width, height, bgcolor='#ffffff'): ' Blend the `img` onto a canvas with the specified background color and size ' w, h = img.width(), img.height() scaled, nw, nh = fit_image(w, h, width, height) if scaled: img = img.scaled(nw, nh, Qt.AspectRatioMode.IgnoreAspectRatio, Qt.TransformationMode.SmoothTransformation) w, h = nw, nh canvas = QImage(width, height, QImage.Format.Format_RGB32) canvas.fill(QColor(bgcolor)) overlay_image(img, canvas, (width - w)//2, (height - h)//2) return canvas
def __init__(self, parent, widget_for_height=None): ''' You must provide a widget in the layout either here or with setBuddy. The height of the separator is computed using this widget, ''' QWidget.__init__(self, parent) self.bcol = QColor(QPalette.ColorRole.Text) self.update_brush() self.widget_for_height = widget_for_height self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.MinimumExpanding)
def data(self, role): if role == Qt.ItemDataRole.DisplayRole: return (self.cdata + ' [%d]' % len(self.children)) elif role == Qt.ItemDataRole.FontRole: return self.bold_font elif role == Qt.ItemDataRole.ForegroundRole and self.category == _( 'Scheduled'): return (QColor(0, 255, 0)) elif role == Qt.ItemDataRole.UserRole: return '::category::{}'.format(self.sortq[0]) return None
def draw(self, painter): for l in self.layouts: if hasattr(l, 'draw'): # Etch effect for the text painter.save() painter.setRenderHints(QPainter.RenderHint.TextAntialiasing | QPainter.RenderHint.Antialiasing) painter.save() painter.setPen(QColor(255, 255, 255, 125)) l.draw(painter, QPointF(1, 1)) painter.restore() l.draw(painter, QPointF()) painter.restore()
def __init__(self, parent): super(CoverDelegate, self).__init__(parent) self._animated_size = 1.0 self.animation = QPropertyAnimation(self, b'animated_size', self) self.animation.setEasingCurve(QEasingCurve.Type.OutInCirc) self.animation.setDuration(500) self.set_dimensions() self.cover_cache = CoverCache() self.render_queue = LifoQueue() self.animating = None self.highlight_color = QColor(Qt.GlobalColor.white) self.rating_font = QFont(rating_font())
def ins_button_clicked(self): row = self.table.currentRow() if row < 0: error_dialog(self, _('Select a cell'), _('Select a cell before clicking the button'), show=True) return self.table.insertRow(row) self.table.setItem(row, 0, QTableWidgetItem()) c = QComboBox(self) c.addItem('') c.addItems(QColor.colorNames()) self.table.setCellWidget(row, 1, c)
def dark_palette(): p = QPalette() disabled_color = QColor(127,127,127) p.setColor(QPalette.ColorRole.Window, dark_color) p.setColor(QPalette.ColorRole.WindowText, dark_text_color) p.setColor(QPalette.ColorRole.Base, QColor(18,18,18)) p.setColor(QPalette.ColorRole.AlternateBase, dark_color) p.setColor(QPalette.ColorRole.ToolTipBase, dark_color) p.setColor(QPalette.ColorRole.ToolTipText, dark_text_color) p.setColor(QPalette.ColorRole.Text, dark_text_color) p.setColor(QPalette.ColorGroup.Disabled, QPalette.ColorRole.Text, disabled_color) p.setColor(QPalette.ColorRole.Button, dark_color) p.setColor(QPalette.ColorRole.ButtonText, dark_text_color) p.setColor(QPalette.ColorGroup.Disabled, QPalette.ColorRole.ButtonText, disabled_color) p.setColor(QPalette.ColorRole.BrightText, Qt.GlobalColor.red) p.setColor(QPalette.ColorRole.Link, dark_link_color) p.setColor(QPalette.ColorRole.Highlight, dark_link_color) p.setColor(QPalette.ColorRole.HighlightedText, Qt.GlobalColor.black) p.setColor(QPalette.ColorGroup.Disabled, QPalette.ColorRole.HighlightedText, disabled_color) return p
def __init__(self, doc): QSyntaxHighlighter.__init__(self, doc) self.colors = {} self.colors['doctype'] = QColor(192, 192, 192) self.colors['entity'] = QColor(128, 128, 128) self.colors['comment'] = QColor(35, 110, 37) if is_dark_theme(): from calibre.gui2.palette import dark_link_color self.colors['tag'] = QColor(186, 78, 188) self.colors['attrname'] = QColor(193, 119, 60) self.colors['attrval'] = dark_link_color else: self.colors['tag'] = QColor(136, 18, 128) self.colors['attrname'] = QColor(153, 69, 0) self.colors['attrval'] = QColor(36, 36, 170)
def paintEvent(self, event): canvas_size = self.rect() width = self.current_pixmap_size.width() extrax = canvas_size.width() - width if extrax < 0: extrax = 0 x = int(extrax // 2) height = self.current_pixmap_size.height() extray = canvas_size.height() - height if extray < 0: extray = 0 y = int(extray // 2) target = QRect(x, y, width, height) p = QPainter(self) p.setRenderHints(QPainter.RenderHint.Antialiasing | QPainter.RenderHint.SmoothPixmapTransform) try: dpr = self.devicePixelRatioF() except AttributeError: dpr = self.devicePixelRatio() spmap = self.pixmap.scaled(target.size() * dpr, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation) spmap.setDevicePixelRatio(dpr) p.drawPixmap(target, spmap) if gprefs['bd_overlay_cover_size']: sztgt = target.adjusted(0, 0, 0, -4) f = p.font() f.setBold(True) p.setFont(f) sz = '\u00a0%d x %d\u00a0' % (self.pixmap.width(), self.pixmap.height()) flags = Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignRight | Qt.TextFlag.TextSingleLine szrect = p.boundingRect(sztgt, flags, sz) p.fillRect(szrect.adjusted(0, 0, 0, 4), QColor(0, 0, 0, 200)) p.setPen(QPen(QColor(255, 255, 255))) p.drawText(sztgt, flags, sz) p.end()
def __init__(self, logger, opts): QGraphicsScene.__init__(self) self.logger, self.opts = logger, opts self.pages = [] self.chapters = [] self.chapter_layout = None self.current_screen = None self.current_page = 0 self.link_map = {} self.chapter_map = {} self.history = History() self.last_search = iter([]) if not opts.white_background: self.setBackgroundBrush(QBrush(QColor(0xee, 0xee, 0xee)))
def set_color(self): r, g, b = gprefs['cover_grid_color'] tex = gprefs['cover_grid_texture'] pal = self.palette() pal.setColor(QPalette.ColorRole.Base, QColor(r, g, b)) self.setPalette(pal) ss = '' if tex: from calibre.gui2.preferences.texture_chooser import texture_path path = texture_path(tex) if path: path = os.path.abspath(path).replace(os.sep, '/') ss += 'background-image: url({});'.format(path) ss += 'background-attachment: fixed;' pm = QPixmap(path) if not pm.isNull(): val = pm.scaled(1, 1).toImage().pixel(0, 0) r, g, b = qRed(val), qGreen(val), qBlue(val) dark = max(r, g, b) < 115 col = '#eee' if dark else '#111' ss += 'color: {};'.format(col) self.delegate.highlight_color = QColor(col) self.setStyleSheet('QListView {{ {} }}'.format(ss))