mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Fix image rendering quality in cover download and PDF covers dialogs on High DPI screens
This commit is contained in:
parent
04d8f2cda5
commit
1e90aaa1a8
@ -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)
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user