class Background(QWidget): # {{{ 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) def update_brush(self): self.brush = QBrush(self.bcol) if self.btex: from calibre.gui2.preferences.texture_chooser import texture_path path = texture_path(self.btex) if path: p = QPixmap(path) try: dpr = self.devicePixelRatioF() except AttributeError: dpr = self.devicePixelRatio() p.setDevicePixelRatio(dpr) self.brush.setTexture(p) self.update() def sizeHint(self): return QSize(200, 120) def paintEvent(self, ev): painter = QPainter(self) painter.fillRect(ev.rect(), self.brush) painter.end()
class Link(QGraphicsRectItem): inactive_brush = QBrush(QColor(0xff, 0xff, 0xff, 0xff)) active_brush = QBrush(QColor(0x00, 0x00, 0x00, 0x59)) def __init__(self, parent, start, stop, refobj, slot): QGraphicsRectItem.__init__(self, start, 0, stop - start, parent.height, parent) self.refobj = refobj self.slot = slot self.brush = self.__class__.inactive_brush self.setPen(QPen(Qt.PenStyle.NoPen)) self.setCursor(Qt.CursorShape.PointingHandCursor) self.setAcceptHoverEvents(True) def hoverEnterEvent(self, event): self.brush = self.__class__.active_brush self.parentItem().update() def hoverLeaveEvent(self, event): self.brush = self.__class__.inactive_brush self.parentItem().update() def mousePressEvent(self, event): self.hoverLeaveEvent(None) self.slot(self.refobj)
def __init__(self, develop=False): self.drawn_once = False self.develop = develop self.title_font = f = QFont() f.setPointSize(self.TITLE_SIZE) f.setBold(True) self.title_height = QFontMetrics(f).lineSpacing() + 2 self.body_font = f = QFont() f.setPointSize(self.BODY_SIZE) self.line_height = QFontMetrics(f).lineSpacing() self.total_height = max(self.LOGO_SIZE, self.title_height + 3 * self.line_height) self.num_font = f = QFont() f.setPixelSize(self.total_height) f.setItalic(True), f.setBold(True) f = QFontMetrics(f) self.num_ch = str(max(3, numeric_version[0])) self.footer_font = f = QFont() f.setPointSize(self.FOOTER_SIZE) f.setItalic(True) self.dpr = QApplication.instance().devicePixelRatio() self.pmap = QPixmap(I('library.png', allow_user_override=False)) self.pmap.setDevicePixelRatio(self.dpr) self.pmap = self.pmap.scaled( int(self.dpr * self.LOGO_SIZE), int(self.dpr * self.LOGO_SIZE), transformMode=Qt.TransformationMode.SmoothTransformation) self.light_brush = QBrush(QColor('#F6F3E9')) self.dark_brush = QBrush(QColor('#39322B')) pmap = QPixmap(int(self.WIDTH * self.dpr), int(self.total_height * self.dpr)) pmap.setDevicePixelRatio(self.dpr) pmap.fill(Qt.GlobalColor.transparent) QSplashScreen.__init__(self, pmap) self.setWindowTitle(__appname__)
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block): painter.fillRect(rect, self.color1) top = title_block.position.y + 2 extra_spacing = subtitle_block.line_spacing // 2 if subtitle_block.line_spacing else title_block.line_spacing // 3 height = title_block.height + subtitle_block.height + extra_spacing + title_block.leading right = rect.right() - self.hmargin width = right - self.hmargin # Draw main banner p = main = QPainterPath(QPointF(self.hmargin, top)) draw_curved_line(p, rect.width() - 2 * self.hmargin, 0, 0.1, -0.1, 0.9, -0.1) deltax = self.GRADE * height p.lineTo(right + deltax, top + height) right_corner = p.currentPosition() draw_curved_line(p, - width - 2 * deltax, 0, 0.1, 0.05, 0.9, 0.05) left_corner = p.currentPosition() p.closeSubpath() # Draw fold rectangles rwidth = self.fold_width yfrac = 0.1 width23 = int(0.67 * rwidth) rtop = top + height * yfrac def draw_fold(x, m=1, corner=left_corner): ans = p = QPainterPath(QPointF(x, rtop)) draw_curved_line(p, rwidth*m, 0, 0.1, 0.1*m, 0.5, -0.2*m) fold_upper = p.currentPosition() p.lineTo(p.currentPosition() + QPointF(-deltax*m, height)) fold_corner = p.currentPosition() draw_curved_line(p, -rwidth*m, 0, 0.2, -0.1*m, 0.8, -0.1*m) draw_curved_line(p, deltax*m, -height, 0.2, 0.1*m, 0.8, 0.1*m) p = inner_fold = QPainterPath(corner) dp = fold_corner - p.currentPosition() draw_curved_line(p, dp.x(), dp.y(), 0.5, 0.3*m, 1, 0*m) p.lineTo(fold_upper), p.closeSubpath() return ans, inner_fold left_fold, left_inner = draw_fold(self.hmargin - width23) right_fold, right_inner = draw_fold(right + width23, m=-1, corner=right_corner) painter.save() painter.setRenderHint(QPainter.RenderHint.Antialiasing) pen = QPen(self.ccolor2) pen.setWidth(3) pen.setJoinStyle(Qt.PenJoinStyle.RoundJoin) painter.setPen(pen) for r in (left_fold, right_fold): painter.fillPath(r, QBrush(self.color2)) painter.drawPath(r) for r in (left_inner, right_inner): painter.fillPath(r, QBrush(self.color2.darker())) painter.drawPath(r) painter.fillPath(main, QBrush(self.color2)) painter.drawPath(main) painter.restore() return self.ccolor2, self.ccolor2, self.ccolor1
def data(self, index, role): if not index.isValid(): return None row, col = index.row(), index.column() if row < 0 or row >= self.rowCount(): return None display_plugin = self.display_plugins[row] if role in [Qt.ItemDataRole.DisplayRole, Qt.ItemDataRole.UserRole]: if col == 0: return display_plugin.name if col == 1: if display_plugin.donation_link: return _('PayPal') if col == 2: return self._get_status(display_plugin) if col == 3: return self._get_display_version( display_plugin.installed_version) if col == 4: return self._get_display_version( display_plugin.available_version) if col == 5: if role == Qt.ItemDataRole.UserRole: return self._get_display_release_date( display_plugin.release_date, 'yyyyMMdd') else: return self._get_display_release_date( display_plugin.release_date) if col == 6: return self._get_display_version( display_plugin.calibre_required_version) if col == 7: return display_plugin.author elif role == Qt.ItemDataRole.DecorationRole: if col == 0: return self._get_status_icon(display_plugin) if col == 1: if display_plugin.donation_link: return QIcon(I('donate.png')) elif role == Qt.ItemDataRole.ToolTipRole: if col == 1 and display_plugin.donation_link: return _( 'This plugin is FREE but you can reward the developer for their effort\n' 'by donating to them via PayPal.\n\n' 'Right-click and choose Donate to reward: ' ) + display_plugin.author else: return self._get_status_tooltip(display_plugin) elif role == Qt.ItemDataRole.ForegroundRole: if col != 1: # Never change colour of the donation column if display_plugin.is_deprecated: return QBrush(Qt.GlobalColor.blue) if display_plugin.is_disabled(): return QBrush(Qt.GlobalColor.gray) return None
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 update_brush(self): self.brush = QBrush(self.bcol) if self.btex: from calibre.gui2.preferences.texture_chooser import texture_path path = texture_path(self.btex) if path: p = QPixmap(path) try: dpr = self.devicePixelRatioF() except AttributeError: dpr = self.devicePixelRatio() p.setDevicePixelRatio(dpr) self.brush.setTexture(p) self.update()
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 do_insert_link(self, *args): link, name, is_image = self.ask_link() if not link: return url = self.parse_link(link) if url.isValid(): url = unicode_type(url.toString(NO_URL_FORMATTING)) self.focus_self() with self.editing_cursor() as c: if is_image: c.insertImage(url) else: oldfmt = QTextCharFormat(c.charFormat()) fmt = QTextCharFormat() fmt.setAnchor(True) fmt.setAnchorHref(url) fmt.setForeground(QBrush(self.palette().color(QPalette.ColorRole.Link))) if name or not c.hasSelection(): c.mergeCharFormat(fmt) c.insertText(name or url) else: pos, anchor = c.position(), c.anchor() start, end = min(pos, anchor), max(pos, anchor) for i in range(start, end): cur = self.textCursor() cur.setPosition(i), cur.setPosition(i + 1, QTextCursor.MoveMode.KeepAnchor) cur.mergeCharFormat(fmt) c.setPosition(c.position()) c.setCharFormat(oldfmt) else: error_dialog(self, _('Invalid URL'), _('The url %r is invalid') % link, show=True)
def __init__(self, font_loader, canvas, logger, opts, ruby_tags, link_activated, width=0, height=0): if hasattr(canvas, 'canvaswidth'): width, height = canvas.canvaswidth, canvas.canvasheight _Canvas.__init__(self, font_loader, logger, opts, width=width, height=height) self.block_id = canvas.id self.ruby_tags = ruby_tags self.link_activated = link_activated self.text_width = width fg = canvas.framecolor bg = canvas.bgcolor if not opts.visual_debug and canvas.framemode != 'none': self.setPen(Pen(fg, canvas.framewidth)) self.setBrush(QBrush(Color(bg))) self.items = [] for po in canvas: obj = po.object item = object_factory(self, obj, respect_max_y=True) if item: self.items.append((item, po.x1, po.y1))
def corner(): b = QBrush(self.ccolor1) p.fillPath(path, b) p.rotate(90), p.translate(100, -100), p.scale(1, -1), p.translate( -103, -97) p.fillPath(path, b) p.setWorldTransform(QTransform())
def do_test(self): selections = [] self.match_locs = [] class Pos: python: int = 0 qt: int = 0 if self.regex_valid(): text = str(self.preview.toPlainText()) regex = str(self.regex.text()) cursor = QTextCursor(self.preview.document()) extsel = QTextEdit.ExtraSelection() extsel.cursor = cursor extsel.format.setBackground(QBrush(Qt.GlobalColor.yellow)) with suppress(Exception): prev = Pos() for match in compile_regular_expression(regex).finditer(text): es = QTextEdit.ExtraSelection(extsel) qtchars_to_start = utf16_length( text[prev.python:match.start()]) qt_pos = prev.qt + qtchars_to_start prev.python = match.end() prev.qt = qt_pos + utf16_length(match.group()) es.cursor.setPosition(qt_pos, QTextCursor.MoveMode.MoveAnchor) es.cursor.setPosition(prev.qt, QTextCursor.MoveMode.KeepAnchor) selections.append(es) self.match_locs.append((qt_pos, prev.qt)) self.preview.setExtraSelections(selections) if self.match_locs: self.next.setEnabled(True) self.previous.setEnabled(True) self.occurrences.setText(str(len(self.match_locs)))
def __init__(self, gui): QWidget.__init__(self, gui) self.setObjectName('jobs_pointer') self.setVisible(False) self.resize(100, 80) self.animation = QPropertyAnimation(self, b"geometry", self) self.animation.setDuration(750) self.animation.setLoopCount(2) self.animation.setEasingCurve(QEasingCurve.Type.Linear) self.animation.finished.connect(self.hide) taily, heady = 0, 55 self.arrow_path = QPainterPath(QPointF(40, taily)) self.arrow_path.lineTo(40, heady) self.arrow_path.lineTo(20, heady) self.arrow_path.lineTo(50, self.height()) self.arrow_path.lineTo(80, heady) self.arrow_path.lineTo(60, heady) self.arrow_path.lineTo(60, taily) self.arrow_path.closeSubpath() c = self.palette().color(QPalette.ColorGroup.Active, QPalette.ColorRole.WindowText) self.color = QColor(c) self.color.setAlpha(100) self.brush = QBrush(self.color, Qt.BrushStyle.SolidPattern)
def data(self, index, role): if not index.isValid(): return None if index.internalId() == 0: if role == Qt.ItemDataRole.DisplayRole: return self.categories[index.row()] else: plugin = self.index_to_plugin(index) disabled = is_disabled(plugin) if role == Qt.ItemDataRole.DisplayRole: ver = '.'.join(map(str, plugin.version)) desc = '\n'.join(textwrap.wrap(plugin.description, 100)) ans = '%s (%s) %s %s\n%s' % (plugin.name, ver, _('by'), plugin.author, desc) c = plugin_customization(plugin) if c and not disabled: ans += _('\nCustomization: ') + c if disabled: ans += _('\n\nThis plugin has been disabled') if plugin.installation_type is PluginInstallationType.SYSTEM: ans += _( '\n\nThis plugin is installed system-wide and can not be managed from within calibre' ) return (ans) if role == Qt.ItemDataRole.DecorationRole: return self.disabled_icon if disabled else self.icon if role == Qt.ItemDataRole.ForegroundRole and disabled: return (QBrush(Qt.GlobalColor.gray)) if role == Qt.ItemDataRole.UserRole: return plugin return None
def do_test(self): selections = [] self.match_locs = [] if self.regex_valid(): text = unicode_type(self.preview.toPlainText()) regex = unicode_type(self.regex.text()) cursor = QTextCursor(self.preview.document()) extsel = QTextEdit.ExtraSelection() extsel.cursor = cursor extsel.format.setBackground(QBrush(Qt.GlobalColor.yellow)) try: for match in compile_regular_expression(regex).finditer(text): es = QTextEdit.ExtraSelection(extsel) es.cursor.setPosition(match.start(), QTextCursor.MoveMode.MoveAnchor) es.cursor.setPosition(match.end(), QTextCursor.MoveMode.KeepAnchor) selections.append(es) self.match_locs.append((match.start(), match.end())) except: pass self.preview.setExtraSelections(selections) if self.match_locs: self.next.setEnabled(True) self.previous.setEnabled(True) self.occurrences.setText(unicode_type(len(self.match_locs)))
def do_background(self): col = QColorDialog.getColor(Qt.GlobalColor.white, self, _('Choose background color'), QColorDialog.ColorDialogOption.ShowAlphaChannel) if col.isValid(): fmt = QTextCharFormat() fmt.setBackground(QBrush(col)) with self.editing_cursor() as c: c.mergeCharFormat(fmt)
def set_marked(self, marked): if marked: marked_brush = QBrush( Qt.GlobalColor.darkGray if QApplication.instance( ).is_dark_theme else Qt.GlobalColor.lightGray) self.set_background(marked_brush) else: self.set_background()
def __init__(self): self.fill = QBrush(Qt.GlobalColor.white) self.stroke = QPen() self.opacity = 1.0 self.transform = QTransform() self.brush_origin = QPointF() self.clip_updated = False self.do_fill = False self.do_stroke = True self.qt_pattern_cache = {}
def copy(self): ans = GraphicsState() ans.fill = QBrush(self.fill) ans.stroke = QPen(self.stroke) ans.opacity = self.opacity ans.transform = self.transform * QTransform() ans.brush_origin = QPointF(self.brush_origin) ans.clip_updated = self.clip_updated ans.do_fill, ans.do_stroke = self.do_fill, self.do_stroke return ans
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block): if not self.PATH_CACHE: from calibre.utils.speedups import svg_path_to_painter_path try: self.__class__.PATH_CACHE['corner'] = svg_path_to_painter_path( self.CORNER_VECTOR) except Exception: import traceback traceback.print_exc() p = painter painter.setRenderHint(QPainter.RenderHint.Antialiasing) g = QRadialGradient(QPointF(rect.center()), rect.width()) g.setColorAt(0, self.color1), g.setColorAt(1, self.color2) painter.fillRect(rect, QBrush(g)) painter.save() painter.setWindow(0, 0, *self.VIEWPORT) try: path = self.PATH_CACHE['corner'] except KeyError: path = QPainterPath() pen = p.pen() pen.setColor(self.ccolor1) p.setPen(pen) def corner(): b = QBrush(self.ccolor1) p.fillPath(path, b) p.rotate(90), p.translate(100, -100), p.scale(1, -1), p.translate( -103, -97) p.fillPath(path, b) p.setWorldTransform(QTransform()) # Top-left corner corner() # Top right corner p.scale(-1, 1), p.translate(-400, 0), corner() # Bottom left corner p.scale(1, -1), p.translate(0, -500), corner() # Bottom right corner p.scale(-1, -1), p.translate(-400, -500), corner() for y in (28.4, 471.7): p.drawLine(QPointF(160, y), QPointF(240, y)) for x in (31.3, 368.7): p.drawLine(QPointF(x, 155), QPointF(x, 345)) pen.setWidthF(1.8) p.setPen(pen) for y in (23.8, 476.7): p.drawLine(QPointF(160, y), QPointF(240, y)) for x in (26.3, 373.7): p.drawLine(QPointF(x, 155), QPointF(x, 345)) painter.restore() return self.ccolor2, self.ccolor2, self.ccolor1
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 paintEvent(self, ev): br = ev.region().boundingRect() p = QPainter(self) p.setOpacity(0.2) p.fillRect(br, QBrush(self.palette().text())) p.end() QWidget.paintEvent(self, ev) p = QPainter(self) p.setClipRect(br) f = p.font() f.setBold(True) f.setPointSize(20) p.setFont(f) p.setPen(Qt.PenStyle.SolidLine) r = QRect(0, self.dummy.geometry().top() + 10, self.geometry().width(), 150) p.drawText( r, Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop | Qt.TextFlag.TextSingleLine, self.text) p.end()
def paint(self, painter, option, widget): x, y = 0, 0 + self.height - self.descent if self.vdebug: painter.save() painter.setPen(QPen(Qt.GlobalColor.yellow, 1, Qt.PenStyle.DotLine)) painter.drawRect(self.boundingRect()) painter.restore() painter.save() painter.setPen(QPen(Qt.PenStyle.NoPen)) for c in self.children(): painter.setBrush(c.brush) painter.drawRect(c.boundingRect()) painter.restore() painter.save() for tok in self.tokens: if isinstance(tok, numbers.Number): x += tok elif isinstance(tok, Word): painter.setFont(tok.font) if tok.highlight: painter.save() painter.setPen(QPen(Qt.PenStyle.NoPen)) painter.setBrush(QBrush(Qt.GlobalColor.yellow)) painter.drawRect(int(x), 0, tok.width, tok.height) painter.restore() painter.setPen(QPen(tok.text_color)) if tok.valign is None: painter.drawText(int(x), int(y), tok.string) elif tok.valign == 'Sub': painter.drawText(int(x + 1), int(y + self.descent / 1.5), tok.string) elif tok.valign == 'Sup': painter.drawText(int(x + 1), int(y - 2. * self.descent), tok.string) x += tok.width else: painter.drawPixmap(int(x), 0, tok.pixmap()) x += tok.width painter.restore()
def __init__(self, parent, view, row, link_delegate): QDialog.__init__(self, parent) self.normal_brush = QBrush(Qt.GlobalColor.white) self.marked_brush = QBrush(Qt.GlobalColor.lightGray) self.marked = None self.gui = parent self.splitter = QSplitter(self) self._l = l = QVBoxLayout(self) self.setLayout(l) l.addWidget(self.splitter) self.cover = Cover(self, show_size=gprefs['bd_overlay_cover_size']) self.cover.resizeEvent = self.cover_view_resized self.cover.cover_changed.connect(self.cover_changed) self.cover.open_with_requested.connect(self.open_with) self.cover.choose_open_with_requested.connect(self.choose_open_with) self.cover_pixmap = None self.cover.sizeHint = self.details_size_hint self.splitter.addWidget(self.cover) self.details = Details(parent.book_details.book_info, self) self.details.anchor_clicked.connect(self.on_link_clicked) self.link_delegate = link_delegate self.details.setAttribute(Qt.WidgetAttribute.WA_OpaquePaintEvent, False) palette = self.details.palette() self.details.setAcceptDrops(False) palette.setBrush(QPalette.ColorRole.Base, Qt.GlobalColor.transparent) self.details.setPalette(palette) self.c = QWidget(self) self.c.l = l2 = QGridLayout(self.c) l2.setContentsMargins(0, 0, 0, 0) self.c.setLayout(l2) l2.addWidget(self.details, 0, 0, 1, -1) self.splitter.addWidget(self.c) self.fit_cover = QCheckBox(_('Fit &cover within view'), self) self.fit_cover.setChecked( gprefs.get('book_info_dialog_fit_cover', True)) self.hl = hl = QHBoxLayout() hl.setContentsMargins(0, 0, 0, 0) l2.addLayout(hl, l2.rowCount(), 0, 1, -1) hl.addWidget(self.fit_cover), hl.addStretch() self.clabel = QLabel( '<div style="text-align: right"><a href="calibre:conf" title="{}" style="text-decoration: none">{}</a>' .format(_('Configure this view'), _('Configure'))) self.clabel.linkActivated.connect(self.configure) hl.addWidget(self.clabel) self.previous_button = QPushButton(QIcon(I('previous.png')), _('&Previous'), self) self.previous_button.clicked.connect(self.previous) l2.addWidget(self.previous_button, l2.rowCount(), 0) self.next_button = QPushButton(QIcon(I('next.png')), _('&Next'), self) self.next_button.clicked.connect(self.next) l2.addWidget(self.next_button, l2.rowCount() - 1, 1) self.view = view self.path_to_book = None self.current_row = None self.refresh(row) self.view.model().new_bookdisplay_data.connect(self.slave) self.fit_cover.stateChanged.connect(self.toggle_cover_fit) self.ns = QShortcut(QKeySequence('Alt+Right'), self) self.ns.activated.connect(self.next) self.ps = QShortcut(QKeySequence('Alt+Left'), self) self.ps.activated.connect(self.previous) self.next_button.setToolTip( _('Next [%s]') % unicode_type(self.ns.key().toString( QKeySequence.SequenceFormat.NativeText))) self.previous_button.setToolTip( _('Previous [%s]') % unicode_type(self.ps.key().toString( QKeySequence.SequenceFormat.NativeText))) geom = QCoreApplication.instance().desktop().availableGeometry(self) screen_height = geom.height() - 100 screen_width = geom.width() - 100 self.resize(max(int(screen_width / 2), 700), screen_height) saved_layout = gprefs.get('book_info_dialog_layout', None) if saved_layout is not None: try: QApplication.instance().safe_restore_geometry( self, saved_layout[0]) self.splitter.restoreState(saved_layout[1]) except Exception: pass from calibre.gui2.ui import get_gui ema = get_gui().iactions['Edit Metadata'].menuless_qaction a = self.ema = QAction('edit metadata', self) a.setShortcut(ema.shortcut()) self.addAction(a) a.triggered.connect(self.edit_metadata)
def __call__(self, painter, rect, color_theme, title_block, subtitle_block, footer_block): g = QLinearGradient(QPointF(0, 0), QPointF(0, rect.height())) g.setStops([(0, self.color1), (0.7, self.color2), (1, self.color1)]) painter.fillRect(rect, QBrush(g)) return self.ccolor1, self.ccolor1, self.ccolor1
def __init__(self, color, width): QPen.__init__( self, QBrush(Color(color)), width, (Qt.PenStyle.SolidLine if width > 0 else Qt.PenStyle.NoPen))
def update_brush(self): self.brush = QBrush(self.bcol) self.update()
class SplashScreen(QSplashScreen): TITLE_SIZE = 20 # pt BODY_SIZE = 12 # pt FOOTER_SIZE = 9 # pt LOGO_SIZE = 96 # px WIDTH = 550 # px def __init__(self, develop=False): self.drawn_once = False self.develop = develop self.title_font = f = QFont() f.setPointSize(self.TITLE_SIZE) f.setBold(True) self.title_height = QFontMetrics(f).lineSpacing() + 2 self.body_font = f = QFont() f.setPointSize(self.BODY_SIZE) self.line_height = QFontMetrics(f).lineSpacing() self.total_height = max(self.LOGO_SIZE, self.title_height + 3 * self.line_height) self.num_font = f = QFont() f.setPixelSize(self.total_height) f.setItalic(True), f.setBold(True) f = QFontMetrics(f) self.num_ch = str(max(3, numeric_version[0])) self.footer_font = f = QFont() f.setPointSize(self.FOOTER_SIZE) f.setItalic(True) self.dpr = QApplication.instance().devicePixelRatio() self.pmap = QPixmap(I('library.png', allow_user_override=False)) self.pmap.setDevicePixelRatio(self.dpr) self.pmap = self.pmap.scaled( int(self.dpr * self.LOGO_SIZE), int(self.dpr * self.LOGO_SIZE), transformMode=Qt.TransformationMode.SmoothTransformation) self.light_brush = QBrush(QColor('#F6F3E9')) self.dark_brush = QBrush(QColor('#39322B')) pmap = QPixmap(int(self.WIDTH * self.dpr), int(self.total_height * self.dpr)) pmap.setDevicePixelRatio(self.dpr) pmap.fill(Qt.GlobalColor.transparent) QSplashScreen.__init__(self, pmap) self.setWindowTitle(__appname__) 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 show_message(self, msg): self.showMessage(msg) self.wait_for_draw() def wait_for_draw(self): # Without this the splash screen is not painted on linux and windows self.drawn_once = False st = monotonic() while not self.drawn_once and (monotonic() - st < 0.1): QApplication.instance().processEvents() def keyPressEvent(self, ev): if not self.develop: return QSplashScreen.keyPressEvent(self, ev) ev.accept() QApplication.instance().quit()