Fix image rendering quality in cover download and PDF covers dialogs on High DPI screens

This commit is contained in:
Kovid Goyal 2016-08-24 20:48:23 +05:30
parent 04d8f2cda5
commit 1e90aaa1a8
2 changed files with 39 additions and 14 deletions

View File

@ -12,15 +12,27 @@ from threading import Thread
from glob import glob from glob import glob
import sip import sip
from PyQt5.Qt import (QDialog, QApplication, QLabel, QGridLayout, from PyQt5.Qt import (
QDialogButtonBox, Qt, pyqtSignal, QListWidget, QDialog, QApplication, QLabel, QGridLayout, QDialogButtonBox, Qt,
QListWidgetItem, QSize, QIcon) pyqtSignal, QListWidget, QListWidgetItem, QSize, QPixmap, QStyledItemDelegate
)
from calibre import as_unicode from calibre import as_unicode
from calibre.ebooks.metadata.pdf import page_images from calibre.ebooks.metadata.pdf import page_images
from calibre.gui2 import error_dialog, file_icon_provider from calibre.gui2 import error_dialog, file_icon_provider
from calibre.ptempfile import PersistentTemporaryDirectory from calibre.ptempfile import PersistentTemporaryDirectory
class CoverDelegate(QStyledItemDelegate):
def paint(self, painter, option, index):
QStyledItemDelegate.paint(self, painter, option, index)
style = QApplication.style()
# Ensure the cover is rendered over any selection rect
style.drawItemPixmap(painter, option.rect, Qt.AlignTop|Qt.AlignHCenter,
QPixmap(index.data(Qt.DecorationRole)))
class PDFCovers(QDialog): class PDFCovers(QDialog):
'Choose a cover from the first few pages of a PDF' 'Choose a cover from the first few pages of a PDF'
@ -39,6 +51,8 @@ class PDFCovers(QDialog):
self.covers = c = QListWidget(self) self.covers = c = QListWidget(self)
l.addWidget(c) l.addWidget(c)
self.item_delegate = CoverDelegate(self)
c.setItemDelegate(self.item_delegate)
c.setIconSize(QSize(120, 160)) c.setIconSize(QSize(120, 160))
c.setSelectionMode(c.SingleSelection) c.setSelectionMode(c.SingleSelection)
c.setViewMode(c.IconMode) c.setViewMode(c.IconMode)
@ -96,8 +110,11 @@ class PDFCovers(QDialog):
self.reject() self.reject()
return return
for f in sorted(files): for i, f in enumerate(sorted(files)):
i = QListWidgetItem(QIcon(f), '') p = QPixmap(f).scaled(self.covers.iconSize()*self.devicePixelRatio(), aspectRatioMode=Qt.IgnoreAspectRatio, transformMode=Qt.SmoothTransformation)
p.setDevicePixelRatio(self.devicePixelRatio())
i = QListWidgetItem(_('page %d') % (i + 1))
i.setData(Qt.DecorationRole, p)
i.setData(Qt.UserRole, f) i.setData(Qt.UserRole, f)
self.covers.addItem(i) self.covers.addItem(i)
@ -107,4 +124,3 @@ if __name__ == '__main__':
d = PDFCovers(sys.argv[-1]) d = PDFCovers(sys.argv[-1])
d.exec_() d.exec_()
print (d.cover_path) print (d.cover_path)

View File

@ -81,6 +81,8 @@ class RichTextDelegate(QStyledItemDelegate): # {{{
class CoverDelegate(QStyledItemDelegate): # {{{ class CoverDelegate(QStyledItemDelegate): # {{{
ICON_SIZE = 150, 200
needs_redraw = pyqtSignal() needs_redraw = pyqtSignal()
def __init__(self, parent): def __init__(self, parent):
@ -633,8 +635,9 @@ class CoversModel(QAbstractListModel): # {{{
if current_cover is None: if current_cover is None:
current_cover = QPixmap(I('default_cover.png')) current_cover = QPixmap(I('default_cover.png'))
current_cover.setDevicePixelRatio(QApplication.instance().devicePixelRatio())
self.blank = QPixmap(I('blank.png')).scaled(150, 200) self.blank = QPixmap(I('blank.png')).scaled(*CoverDelegate.ICON_SIZE)
self.cc = current_cover self.cc = current_cover
self.reset_covers(do_reset=False) self.reset_covers(do_reset=False)
@ -652,8 +655,10 @@ class CoversModel(QAbstractListModel): # {{{
def get_item(self, src, pmap, waiting=False): def get_item(self, src, pmap, waiting=False):
sz = '%dx%d'%(pmap.width(), pmap.height()) sz = '%dx%d'%(pmap.width(), pmap.height())
text = (src + '\n' + sz) text = (src + '\n' + sz)
scaled = pmap.scaled(150, 200, Qt.IgnoreAspectRatio, scaled = pmap.scaled(
Qt.SmoothTransformation) int(CoverDelegate.ICON_SIZE[0] * pmap.devicePixelRatio()), int(CoverDelegate.ICON_SIZE[1] * pmap.devicePixelRatio()),
Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
scaled.setDevicePixelRatio(pmap.devicePixelRatio())
return (text, (scaled), pmap, waiting) return (text, (scaled), pmap, waiting)
def rowCount(self, parent=None): def rowCount(self, parent=None):
@ -715,6 +720,12 @@ class CoversModel(QAbstractListModel): # {{{
return self.index(r) return self.index(r)
return self.index(0) return self.index(0)
def load_pixmap(self, data):
pmap = QPixmap()
pmap.loadFromData(data)
pmap.setDevicePixelRatio(QApplication.instance().devicePixelRatio())
return pmap
def update_result(self, plugin_name, width, height, data): def update_result(self, plugin_name, width, height, data):
if plugin_name.endswith('}'): if plugin_name.endswith('}'):
# multi cover plugin # multi cover plugin
@ -724,8 +735,7 @@ class CoversModel(QAbstractListModel): # {{{
return return
plugin = plugin[0] plugin = plugin[0]
last_row = max(self.plugin_map[plugin]) last_row = max(self.plugin_map[plugin])
pmap = QPixmap() pmap = self.load_pixmap(data)
pmap.loadFromData(data)
if pmap.isNull(): if pmap.isNull():
return return
self.beginInsertRows(QModelIndex(), last_row, last_row) self.beginInsertRows(QModelIndex(), last_row, last_row)
@ -745,8 +755,7 @@ class CoversModel(QAbstractListModel): # {{{
break break
if idx is None: if idx is None:
return return
pmap = QPixmap() pmap = self.load_pixmap(data)
pmap.loadFromData(data)
if pmap.isNull(): if pmap.isNull():
return return
self.covers[idx] = self.get_item(plugin_name, pmap, waiting=False) self.covers[idx] = self.get_item(plugin_name, pmap, waiting=False)
@ -774,7 +783,7 @@ class CoversView(QListView): # {{{
self.setWrapping(True) self.setWrapping(True)
self.setResizeMode(self.Adjust) self.setResizeMode(self.Adjust)
self.setGridSize(QSize(190, 260)) self.setGridSize(QSize(190, 260))
self.setIconSize(QSize(150, 200)) self.setIconSize(QSize(*CoverDelegate.ICON_SIZE))
self.setSelectionMode(self.SingleSelection) self.setSelectionMode(self.SingleSelection)
self.setViewMode(self.IconMode) self.setViewMode(self.IconMode)