From ba8363f0778bee776e1045311c436a4cf3a96484 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 26 Aug 2016 16:40:15 +0530 Subject: [PATCH] More hidpi fixes --- src/calibre/gui2/metadata/single_download.py | 2 +- src/calibre/gui2/proceed.py | 13 +++++---- .../gui2/store/search/download_thread.py | 2 +- src/calibre/gui2/store/search/models.py | 23 +++++++-------- src/calibre/gui2/store/search/results_view.py | 28 ++++++++++++++++++- src/calibre/gui2/update.py | 5 ++-- 6 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/calibre/gui2/metadata/single_download.py b/src/calibre/gui2/metadata/single_download.py index 456edde638..6e1a00e862 100644 --- a/src/calibre/gui2/metadata/single_download.py +++ b/src/calibre/gui2/metadata/single_download.py @@ -637,7 +637,7 @@ class CoversModel(QAbstractListModel): # {{{ current_cover = QPixmap(I('default_cover.png')) current_cover.setDevicePixelRatio(QApplication.instance().devicePixelRatio()) - self.blank = QPixmap(I('blank.png')).scaled(*CoverDelegate.ICON_SIZE) + self.blank = QIcon(I('blank.png')).pixmap(*CoverDelegate.ICON_SIZE) self.cc = current_cover self.reset_covers(do_reset=False) diff --git a/src/calibre/gui2/proceed.py b/src/calibre/gui2/proceed.py index 00e7a1f782..6163fe0ae7 100644 --- a/src/calibre/gui2/proceed.py +++ b/src/calibre/gui2/proceed.py @@ -10,9 +10,9 @@ __docformat__ = 'restructuredtext en' from collections import namedtuple from PyQt5.Qt import ( - QWidget, Qt, QLabel, QVBoxLayout, QPixmap, QDialogButtonBox, QApplication, QTimer, + QWidget, Qt, QLabel, QVBoxLayout, QDialogButtonBox, QApplication, QTimer, QPixmap, QSize, pyqtSignal, QIcon, QPlainTextEdit, QCheckBox, QPainter, QHBoxLayout, QFontMetrics, - QPainterPath, QRectF, pyqtProperty, QPropertyAnimation, QEasingCurve, QSizePolicy) + QPainterPath, QRectF, pyqtProperty, QPropertyAnimation, QEasingCurve, QSizePolicy, QImage) from calibre.constants import __version__ from calibre.gui2.dialogs.message_box import ViewLog @@ -58,7 +58,7 @@ class Icon(QWidget): elif icon is None: self.icon = self.default_icon else: - self.icon = QPixmap(I(icon)).scaled(self.sizeHint(), transformMode=Qt.SmoothTransformation) + self.icon = QIcon(I(icon)).pixmap(self.sizeHint()) self.update() def sizeHint(self): @@ -263,9 +263,11 @@ class ProceedQuestion(QWidget): if self.rendered_pixmap is not None: return - p = QPixmap(self.size()) + dpr = getattr(self, 'devicePixelRatioF', self.devicePixelRatio)() + p = QImage(dpr * self.size(), QImage.Format_ARGB32_Premultiplied) + p.setDevicePixelRatio(dpr) self.render(p) - self.rendered_pixmap = p + self.rendered_pixmap = QPixmap.fromImage(p) self.original_visibility = v = [] for child in self.findChildren(QWidget): if child.isVisible(): @@ -412,4 +414,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/src/calibre/gui2/store/search/download_thread.py b/src/calibre/gui2/store/search/download_thread.py index 90e760af4c..a4dfba7fdc 100644 --- a/src/calibre/gui2/store/search/download_thread.py +++ b/src/calibre/gui2/store/search/download_thread.py @@ -166,7 +166,7 @@ class CoverThread(Thread): else: with closing(self.br.open(result.cover_url, timeout=timeout)) as f: result.cover_data = f.read() - result.cover_data = scale_image(result.cover_data, 64, 64)[2] + result.cover_data = scale_image(result.cover_data, 256, 256)[2] callback() self.tasks.task_done() except: diff --git a/src/calibre/gui2/store/search/models.py b/src/calibre/gui2/store/search/models.py index 7088452292..83ebb976e2 100644 --- a/src/calibre/gui2/store/search/models.py +++ b/src/calibre/gui2/store/search/models.py @@ -10,7 +10,7 @@ import re, string from operator import attrgetter from PyQt5.Qt import (Qt, QAbstractItemModel, QPixmap, QModelIndex, QSize, - pyqtSignal) + pyqtSignal, QIcon, QApplication) from calibre import force_unicode from calibre.gui2 import FunctionDispatcher @@ -39,20 +39,16 @@ class Matches(QAbstractItemModel): HEADERS = [_('Cover'), _('Title'), _('Price'), _('DRM'), _('Store'), _('Download'), _('Affiliate')] HTML_COLS = (1, 4) + IMG_COLS = (0, 3, 5, 6) def __init__(self, cover_thread_count=2, detail_thread_count=4): QAbstractItemModel.__init__(self) - self.DRM_LOCKED_ICON = QPixmap(I('drm-locked.png')).scaledToHeight(64, - Qt.SmoothTransformation) - self.DRM_UNLOCKED_ICON = QPixmap(I('drm-unlocked.png')).scaledToHeight(64, - Qt.SmoothTransformation) - self.DRM_UNKNOWN_ICON = QPixmap(I('dialog_question.png')).scaledToHeight(64, - Qt.SmoothTransformation) - self.DONATE_ICON = QPixmap(I('donate.png')).scaledToHeight(16, - Qt.SmoothTransformation) - self.DOWNLOAD_ICON = QPixmap(I('arrow-down.png')).scaledToHeight(16, - Qt.SmoothTransformation) + self.DRM_LOCKED_ICON = QIcon(I('drm-locked.png')) + self.DRM_UNLOCKED_ICON = QIcon(I('drm-unlocked.png')) + self.DRM_UNKNOWN_ICON = QIcon(I('dialog_question.png')) + self.DONATE_ICON = QIcon(I('donate.png')) + self.DOWNLOAD_ICON = QIcon(I('arrow-down.png')) # All matches. Used to determine the order to display # self.matches because the SearchFilter returns @@ -206,13 +202,14 @@ class Matches(QAbstractItemModel): elif col == 2: return (result.price) elif col == 4: - return ('%s
%s' % (result.store_name, result.formats)) + return ('%s
%s
' % (result.store_name, result.formats)) return None elif role == Qt.DecorationRole: if col == 0 and result.cover_data: p = QPixmap() p.loadFromData(result.cover_data) - return (p) + p.setDevicePixelRatio(QApplication.instance().devicePixelRatio()) + return p if col == 3: if result.drm == SearchResult.DRM_LOCKED: return (self.DRM_LOCKED_ICON) diff --git a/src/calibre/gui2/store/search/results_view.py b/src/calibre/gui2/store/search/results_view.py index d03a313310..6a20d894f5 100644 --- a/src/calibre/gui2/store/search/results_view.py +++ b/src/calibre/gui2/store/search/results_view.py @@ -8,11 +8,34 @@ __docformat__ = 'restructuredtext en' from functools import partial -from PyQt5.Qt import (pyqtSignal, QMenu, QTreeView) +from PyQt5.Qt import ( + pyqtSignal, QMenu, QTreeView, QStyledItemDelegate, QModelIndex, Qt, QIcon) +from calibre import fit_image from calibre.gui2.metadata.single_download import RichTextDelegate from calibre.gui2.store.search.models import Matches +class ImageDelegate(QStyledItemDelegate): + + def paint(self, painter, option, index): + QStyledItemDelegate.paint(self, painter, option, QModelIndex()) + img = index.data(Qt.DecorationRole) + if img: + h = option.rect.height() - 4 + w = option.rect.width() + if isinstance(img, QIcon): + img = img.pixmap(h - 4, h - 4) + dpr = img.devicePixelRatio() + else: + dpr = img.devicePixelRatio() + scaled, nw, nh = fit_image(img.width(), img.height(), w, h) + if scaled: + img = img.scaled(nw*dpr, nh*dpr, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) + iw, ih = int(img.width()/dpr), int(img.height()/dpr) + dx, dy = (option.rect.width() - iw) // 2, (option.rect.height() - ih) // 2 + painter.drawPixmap(option.rect.adjusted(dx, dy, -dx, -dy), img) + + class ResultsView(QTreeView): download_requested = pyqtSignal(object) @@ -25,9 +48,12 @@ class ResultsView(QTreeView): self.setModel(self._model) self.rt_delegate = RichTextDelegate(self) + self.img_delegate = ImageDelegate(self) for i in self._model.HTML_COLS: self.setItemDelegateForColumn(i, self.rt_delegate) + for i in self._model.IMG_COLS: + self.setItemDelegateForColumn(i, self.img_delegate) def contextMenuEvent(self, event): index = self.indexAt(event.pos()) diff --git a/src/calibre/gui2/update.py b/src/calibre/gui2/update.py index 81ea15776b..04d2319b32 100644 --- a/src/calibre/gui2/update.py +++ b/src/calibre/gui2/update.py @@ -6,7 +6,7 @@ from future_builtins import map from threading import Thread, Event from PyQt5.Qt import (QObject, pyqtSignal, Qt, QUrl, QDialog, QGridLayout, - QLabel, QCheckBox, QDialogButtonBox, QIcon, QPixmap) + QLabel, QCheckBox, QDialogButtonBox, QIcon) from calibre.constants import (__appname__, __version__, iswindows, isosx, isportable, is64bit, numeric_version) @@ -105,8 +105,7 @@ class UpdateNotification(QDialog): self.setLayout(self.l) self.logo = QLabel() self.logo.setMaximumWidth(110) - self.logo.setPixmap(QPixmap(I('lt.png')).scaled(100, 100, - Qt.IgnoreAspectRatio, Qt.SmoothTransformation)) + self.logo.setPixmap(QIcon(I('lt.png')).pixmap(100, 100)) ver = calibre_version if ver.endswith('.0'): ver = ver[:-2]