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 show_pages(self): if self.error is not None: error_dialog(self, _('Failed to render'), _('Could not render this PDF file'), show=True, det_msg=self.error) self.reject() return self.stack.stop() files = glob(os.path.join(self.current_tdir, '*.jpg')) + glob(os.path.join(self.current_tdir, '*.jpeg')) if not files and not self.covers.count(): error_dialog(self, _('Failed to render'), _('This PDF has no pages'), show=True) self.reject() return try: dpr = self.devicePixelRatioF() except AttributeError: dpr = self.devicePixelRatio() for i, f in enumerate(sorted(files)): p = QPixmap(f).scaled( self.covers.iconSize()*dpr, aspectRatioMode=Qt.AspectRatioMode.IgnoreAspectRatio, transformMode=Qt.TransformationMode.SmoothTransformation) p.setDevicePixelRatio(dpr) i = QListWidgetItem(_('page %d') % (self.first + i)) i.setData(Qt.ItemDataRole.DecorationRole, p) i.setData(Qt.ItemDataRole.UserRole, f) self.covers.addItem(i) self.first += len(files) if len(files) == PAGES_PER_RENDER: self.more_pages.setVisible(True)
def render_emblems(item, emblems): emblems = tuple(emblems) if not emblems: return icon = self.rendered_emblem_cache.get(emblems, None) if icon is None: pixmaps = [] for emblem in emblems: pm = self.emblem_cache.get(emblem, None) if pm is None: pm = self.emblem_cache[emblem] = QIcon(I(emblem)).pixmap(self.iconSize()) pixmaps.append(pm) num = len(pixmaps) w, h = pixmaps[0].width(), pixmaps[0].height() if num == 1: icon = self.rendered_emblem_cache[emblems] = QIcon(pixmaps[0]) else: canvas = QPixmap((num * w) + ((num-1)*2), h) canvas.setDevicePixelRatio(pixmaps[0].devicePixelRatio()) canvas.fill(Qt.GlobalColor.transparent) painter = QPainter(canvas) for i, pm in enumerate(pixmaps): painter.drawPixmap(int(i * (w + 2)/canvas.devicePixelRatio()), 0, pm) painter.end() icon = self.rendered_emblem_cache[emblems] = canvas item.setData(0, Qt.ItemDataRole.DecorationRole, icon)
def __init__(self, current_cover, parent=None): QAbstractListModel.__init__(self, parent) if current_cover is None: current_cover = QPixmap(I('default_cover.png')) current_cover.setDevicePixelRatio(QApplication.instance().devicePixelRatio()) self.blank = QIcon(I('blank.png')).pixmap(*CoverDelegate.ICON_SIZE) self.cc = current_cover self.reset_covers(do_reset=False)
def load(data): p = QPixmap() p.loadFromData(as_bytes(data)) try: dpr = self.devicePixelRatioF() except AttributeError: dpr = self.devicePixelRatio() p.setDevicePixelRatio(dpr) if data and p.isNull(): p = self.failed_img return p
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 render_svg(widget, path): img = QPixmap() rend = QSvgRenderer() if rend.load(path): dpr = getattr(widget, 'devicePixelRatioF', widget.devicePixelRatio)() sz = rend.defaultSize() h = (max_available_height() - 50) w = int(h * sz.height() / float(sz.width())) pd = QImage(w * dpr, h * dpr, QImage.Format.Format_RGB32) pd.fill(Qt.GlobalColor.white) p = QPainter(pd) rend.render(p) p.end() img = QPixmap.fromImage(pd) img.setDevicePixelRatio(dpr) return img
def initialize_metadata_options(self): self.initialize_combos() self.author.editTextChanged.connect(self.deduce_author_sort) mi = self.db.get_metadata(self.book_id, index_is_id=True) self.title.setText(mi.title), self.title.home(False) self.publisher.show_initial_value(mi.publisher if mi.publisher else '') self.publisher.home(False) self.author_sort.setText(mi.author_sort if mi.author_sort else '') self.author_sort.home(False) self.tags.setText(', '.join(mi.tags if mi.tags else [])) self.tags.update_items_cache(self.db.new_api.all_field_names('tags')) self.tags.home(False) self.comment.html = comments_to_html( mi.comments) if mi.comments else '' self.series.show_initial_value(mi.series if mi.series else '') self.series.home(False) if mi.series_index is not None: try: self.series_index.setValue(mi.series_index) except: self.series_index.setValue(1.0) cover = self.db.cover(self.book_id, index_is_id=True) if cover: pm = QPixmap() pm.loadFromData(cover) if not pm.isNull(): pm.setDevicePixelRatio( getattr(self, 'devicePixelRatioF', self.devicePixelRatio)()) self.cover.setPixmap(pm) self.cover_data = cover self.set_cover_tooltip(pm) else: pm = QPixmap(I('default_cover.png')) pm.setDevicePixelRatio( getattr(self, 'devicePixelRatioF', self.devicePixelRatio)()) self.cover.setPixmap(pm) self.cover.setToolTip(_('This book has no cover')) for x in ('author', 'series', 'publisher'): x = getattr(self, x) x.lineEdit().deselect() self.series_changed()
def select_cover(self): files = choose_images( self, 'change cover dialog', _('Choose cover for ') + unicode_type(self.title.text())) if not files: return _file = files[0] if _file: _file = os.path.abspath(_file) if not os.access(_file, os.R_OK): d = error_dialog( self.parent(), _('Cannot read'), _('You do not have permission to read the file: ') + _file) d.exec_() return cover = None try: with open(_file, "rb") as f: cover = f.read() except IOError as e: d = error_dialog( self.parent(), _('Error reading file'), _("<p>There was an error reading from file: <br /><b>") + _file + "</b></p><br />" + unicode_type(e)) d.exec_() if cover: pix = QPixmap() pix.loadFromData(cover) pix.setDevicePixelRatio( getattr(self, 'devicePixelRatioF', self.devicePixelRatio)()) if pix.isNull(): d = error_dialog(self.parent(), _('Error reading file'), _file + _(" is not a valid picture")) d.exec_() else: self.cover_path.setText(_file) self.set_cover_tooltip(pix) self.cover.setPixmap(pix) self.cover_changed = True self.cpixmap = pix self.cover_data = cover
def bd_open_cover_with(self, book_id, entry): cpath = self.current_db.new_api.format_abspath(book_id, '__COVER_INTERNAL__') if cpath: if entry is None: pm = QPixmap() pm.load(cpath) pm.setDevicePixelRatio(self.devicePixelRatioF()) if pm.isNull(): open_local_file(cpath) else: from calibre.gui2.image_popup import ImageView iv = ImageView(QApplication.instance().focusWindow(), pm, QUrl.fromLocalFile(cpath), geom_name='book_details_image_view') iv(use_exec=True) return from calibre.gui2.open_with import run_program run_program(entry, cpath, self)
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()
def load_pixmap(self, data): pmap = QPixmap() pmap.loadFromData(data) pmap.setDevicePixelRatio(QApplication.instance().devicePixelRatio()) return pmap
def data(self, index, role): row, col = index.row(), index.column() if row >= len(self.matches): return None result = self.matches[row] if role == Qt.ItemDataRole.DisplayRole: if col == 1: t = result.title if result.title else _('Unknown') a = result.author if result.author else '' return ('<b>%s</b><br><i>%s</i>' % (t, a)) elif col == 2: return (result.price) elif col == 4: return ('<span>%s<br>%s</span>' % (result.store_name, result.formats)) return None elif role == Qt.ItemDataRole.DecorationRole: if col == 0 and result.cover_data: p = QPixmap() p.loadFromData(result.cover_data) p.setDevicePixelRatio(QApplication.instance().devicePixelRatio()) return p if col == 3: if result.drm == SearchResult.DRM_LOCKED: return (self.DRM_LOCKED_ICON) elif result.drm == SearchResult.DRM_UNLOCKED: return (self.DRM_UNLOCKED_ICON) elif result.drm == SearchResult.DRM_UNKNOWN: return (self.DRM_UNKNOWN_ICON) if col == 5: if result.downloads: return (self.DOWNLOAD_ICON) if col == 6: if result.affiliate: return (self.DONATE_ICON) elif role == Qt.ItemDataRole.ToolTipRole: if col == 1: return ('<p>%s</p>' % result.title) elif col == 2: if result.price: return ('<p>' + _( 'Detected price as: %s. Check with the store before making a purchase' ' to verify this price is correct. This price often does not include' ' promotions the store may be running.') % result.price + '</p>') return '<p>' + _( 'No price was found') elif col == 3: if result.drm == SearchResult.DRM_LOCKED: return ('<p>' + _('This book as been detected as having DRM restrictions. This book may not work with your reader and you will have limitations placed upon you as to what you can do with this book. Check with the store before making any purchases to ensure you can actually read this book.') + '</p>') # noqa elif result.drm == SearchResult.DRM_UNLOCKED: return ('<p>' + _('This book has been detected as being DRM Free. You should be able to use this book on any device provided it is in a format calibre supports for conversion. However, before making a purchase double check the DRM status with the store. The store may not be disclosing the use of DRM.') + '</p>') # noqa else: return ('<p>' + _('The DRM status of this book could not be determined. There is a very high likelihood that this book is actually DRM restricted.') + '</p>') # noqa elif col == 4: return ('<p>%s</p>' % result.formats) elif col == 5: if result.downloads: return ('<p>' + _('The following formats can be downloaded directly: %s.') % ', '.join(result.downloads.keys()) + '</p>') elif col == 6: if result.affiliate: return ('<p>' + _('Buying from this store supports the calibre developer: %s.') % result.plugin_author + '</p>') elif role == Qt.ItemDataRole.SizeHintRole: return QSize(64, 64) return None