Draw rounded corners for covers in most places. Preference controlling it is moved to the main section of look & feel since it applies more universally

This commit is contained in:
Kovid Goyal 2024-05-20 07:55:59 +05:30
parent 600270ab08
commit 02b0385b83
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 251 additions and 227 deletions

View File

@ -38,7 +38,9 @@ from qt.core import (
QLocale,
QNetworkProxyFactory,
QObject,
QPainterPath,
QPalette,
QRectF,
QResource,
QSettings,
QSocketNotifier,
@ -426,7 +428,7 @@ def create_defs():
defs['cover_grid_disk_cache_size'] = 2500
defs['cover_grid_show_title'] = False
defs['cover_grid_texture'] = None
defs['cover_grid_corner_radius'] = 0
defs['cover_corner_radius'] = 0
defs['show_vl_tabs'] = False
defs['vl_tabs_closable'] = True
defs['show_highlight_toggle_button'] = False
@ -1756,3 +1758,17 @@ def raise_without_focus(self: QWidget) -> None:
QWidget.raise_and_focus = raise_and_focus
QWidget.raise_without_focus = raise_without_focus
@contextmanager
def clip_border_radius(painter, rect):
painter.save()
r = gprefs['cover_corner_radius']
if r > 0:
pp = QPainterPath()
pp.addRoundedRect(QRectF(rect), r, r)
painter.setClipPath(pp)
try:
yield
finally:
painter.restore()

View File

@ -43,7 +43,18 @@ from calibre.ebooks import BOOK_EXTENSIONS
from calibre.ebooks.metadata.book.base import Metadata, field_metadata
from calibre.ebooks.metadata.book.render import mi_to_html
from calibre.ebooks.metadata.search_internet import all_author_searches, all_book_searches, name_for, url_for_author_search, url_for_book_search
from calibre.gui2 import NO_URL_FORMATTING, choose_save_file, config, default_author_link, gprefs, pixmap_to_data, question_dialog, rating_font, safe_open_url
from calibre.gui2 import (
NO_URL_FORMATTING,
choose_save_file,
clip_border_radius,
config,
default_author_link,
gprefs,
pixmap_to_data,
question_dialog,
rating_font,
safe_open_url,
)
from calibre.gui2.dialogs.confirm_delete import confirm
from calibre.gui2.dialogs.confirm_delete import confirm as confirm_delete
from calibre.gui2.dnd import dnd_get_files, dnd_get_image, dnd_has_extension, dnd_has_image, image_extensions
@ -825,7 +836,8 @@ class CoverView(QWidget): # {{{
dpr = self.devicePixelRatio()
spmap = self.pixmap.scaled(target.size() * dpr, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
spmap.setDevicePixelRatio(dpr)
p.drawPixmap(target, spmap)
with clip_border_radius(p, target):
p.drawPixmap(target, spmap)
if gprefs['bd_overlay_cover_size']:
sztgt = target.adjusted(0, 0, 0, -4)
f = p.font()

View File

@ -10,7 +10,6 @@ import operator
import os
import weakref
from collections import namedtuple
from contextlib import contextmanager
from functools import wraps
from io import BytesIO
from textwrap import wrap
@ -37,13 +36,11 @@ from qt.core import (
QMimeData,
QModelIndex,
QPainter,
QPainterPath,
QPalette,
QPixmap,
QPoint,
QPropertyAnimation,
QRect,
QRectF,
QSize,
QStyledItemDelegate,
QStyleOptionViewItem,
@ -64,7 +61,7 @@ from qt.core import (
from calibre import fit_image, human_readable, prepare_string_for_xml
from calibre.constants import DEBUG, config_dir, islinux
from calibre.ebooks.metadata import fmt_sidx, rating_to_stars
from calibre.gui2 import config, empty_index, gprefs, rating_font
from calibre.gui2 import clip_border_radius, config, empty_index, gprefs, rating_font
from calibre.gui2.dnd import path_from_qurl
from calibre.gui2.gestures import GestureManager
from calibre.gui2.library.caches import CoverCache, ThumbnailCache
@ -565,7 +562,7 @@ class CoverDelegate(QStyledItemDelegate):
return ans
def paint(self, painter, option, index):
with self.clip_border_radius(painter, option.rect):
with clip_border_radius(painter, option.rect):
QStyledItemDelegate.paint(self, painter, option, empty_index) # draw the hover and selection highlights
m = index.model()
db = m.db
@ -662,21 +659,8 @@ class CoverDelegate(QStyledItemDelegate):
finally:
painter.restore()
@contextmanager
def clip_border_radius(self, painter, rect):
painter.save()
r = gprefs['cover_grid_corner_radius']
if r > 0:
pp = QPainterPath()
pp.addRoundedRect(QRectF(rect), r, r)
painter.setClipPath(pp)
try:
yield
finally:
painter.restore()
def paint_cover(self, painter: QPainter, rect: QRect, pixmap: QPixmap):
with self.clip_border_radius(painter, rect):
with clip_border_radius(painter, rect):
painter.drawPixmap(rect, pixmap)
def paint_title(self, painter, rect, db, book_id):

View File

@ -625,8 +625,8 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
r('tag_browser_allow_keyboard_focus', gprefs)
r('bd_show_cover', gprefs)
r('bd_overlay_cover_size', gprefs)
r('cover_corner_radius', gprefs)
r('cover_grid_width', gprefs)
r('cover_grid_corner_radius', gprefs)
r('cover_grid_height', gprefs)
r('cover_grid_cache_size_multiple', gprefs)
r('cover_grid_disk_cache_size', gprefs)

View File

@ -28,26 +28,6 @@
<string>&amp;Main interface</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_9">
<item row="11" column="0">
<widget class="QCheckBox" name="opt_row_numbers_in_book_list">
<property name="text">
<string>Show &amp;row numbers in the book list</string>
</property>
</widget>
</item>
<item row="14" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QLabel" name="opt_color_palette_label">
<property name="text">
@ -58,6 +38,78 @@
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QCheckBox" name="opt_show_splash_screen">
<property name="text">
<string>Show the &amp;splash screen at startup</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QComboBox" name="opt_language">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property>
<property name="minimumContentsLength">
<number>20</number>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="opt_systray_icon">
<property name="text">
<string>Enable s&amp;ystem tray icon (needs restart)</string>
</property>
</widget>
</item>
<item row="12" column="0">
<widget class="QCheckBox" name="opt_row_numbers_in_book_list">
<property name="text">
<string>Show &amp;row numbers in the book list</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Choose &amp;language (needs restart):</string>
</property>
<property name="buddy">
<cstring>opt_language</cstring>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="button_adjust_colors">
<property name="text">
<string>Adjust &amp;colors</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QCheckBox" name="opt_disable_animations">
<property name="toolTip">
<string>Disable all animations. Useful if you have a slow/old computer.</string>
</property>
<property name="text">
<string>Disable &amp;animations</string>
</property>
</widget>
</item>
<item row="13" column="0" colspan="3">
<widget class="QCheckBox" name="opt_booklist_grid">
<property name="text">
<string>Draw a &amp;grid in the book list</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="icon_theme">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
@ -68,47 +120,37 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_widget_style">
<property name="text">
<string>User interface style (&amp;needs restart):</string>
<item row="3" column="2">
<widget class="QComboBox" name="opt_gui_layout">
<property name="maximumSize">
<size>
<width>250</width>
<height>16777215</height>
</size>
</property>
<property name="buddy">
<cstring>opt_ui_style</cstring>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property>
<property name="minimumContentsLength">
<number>20</number>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QLabel" name="label_4">
<item row="8" column="2">
<widget class="QCheckBox" name="opt_show_layout_buttons">
<property name="text">
<string>E&amp;xtra spacing to add between rows in the book list (can be negative):</string>
</property>
<property name="buddy">
<cstring>opt_book_list_extra_row_spacing</cstring>
<string>Show &amp;layout buttons in the status bar</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="opt_systray_icon">
<item row="1" column="2">
<widget class="QPushButton" name="icon_theme_button">
<property name="text">
<string>Enable s&amp;ystem tray icon (needs restart)</string>
<string>Change &amp;icon theme</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QCheckBox" name="opt_disable_animations">
<property name="toolTip">
<string>Disable all animations. Useful if you have a slow/old computer.</string>
</property>
<property name="text">
<string>Disable &amp;animations</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="opt_ui_style"/>
</item>
<item row="8" column="0">
<item row="9" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_2">
@ -129,28 +171,17 @@
</item>
</layout>
</item>
<item row="8" column="2">
<item row="9" column="2">
<widget class="QPushButton" name="change_font_button">
<property name="text">
<string>Change &amp;font (needs restart)</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="opt_book_list_tooltips">
<property name="text">
<string>Show &amp;tooltips in the book list</string>
</property>
</widget>
<item row="0" column="2">
<widget class="QComboBox" name="opt_ui_style"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="icon_theme">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="9" column="0" colspan="3">
<item row="10" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Toolbar</string>
@ -192,40 +223,30 @@
</layout>
</widget>
</item>
<item row="3" column="2">
<widget class="QComboBox" name="opt_gui_layout">
<property name="maximumSize">
<item row="15" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>250</width>
<height>16777215</height>
<width>20</width>
<height>40</height>
</size>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property>
<property name="minimumContentsLength">
<number>20</number>
</property>
</widget>
</spacer>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_7">
<item row="0" column="0">
<widget class="QLabel" name="label_widget_style">
<property name="text">
<string>Choose &amp;language (needs restart):</string>
<string>User interface style (&amp;needs restart):</string>
</property>
<property name="buddy">
<cstring>opt_language</cstring>
<cstring>opt_ui_style</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="icon_theme_button">
<property name="text">
<string>Change &amp;icon theme</string>
</property>
</widget>
</item>
<item row="10" column="2">
<item row="11" column="2">
<widget class="QSpinBox" name="opt_book_list_extra_row_spacing">
<property name="suffix">
<string> px</string>
@ -235,28 +256,14 @@
</property>
</widget>
</item>
<item row="13" column="0">
<item row="14" column="0">
<widget class="QCheckBox" name="opt_dnd_merge">
<property name="text">
<string>Allow using &amp;drag and drop to merge books</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QCheckBox" name="opt_show_layout_buttons">
<property name="text">
<string>Show &amp;layout buttons in the status bar</string>
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QCheckBox" name="opt_show_splash_screen">
<property name="text">
<string>Show the &amp;splash screen at startup</string>
</property>
</widget>
</item>
<item row="6" column="0">
<item row="7" column="0">
<widget class="QCheckBox" name="opt_disable_tray_notification">
<property name="toolTip">
<string>Disable popup notifications when calibre completes jobs such a conversion, sending to device etc. The notifications are sent via the operating system notification facility, if available. Note that on Windows, you have to enable the system tray icon for notifications to work.</string>
@ -266,27 +273,43 @@
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QComboBox" name="opt_language">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property>
<property name="minimumContentsLength">
<number>20</number>
<item row="8" column="0">
<widget class="QCheckBox" name="opt_book_list_tooltips">
<property name="text">
<string>Show &amp;tooltips in the book list</string>
</property>
</widget>
</item>
<item row="12" column="0" colspan="3">
<widget class="QCheckBox" name="opt_booklist_grid">
<item row="11" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Draw a &amp;grid in the book list</string>
<string>E&amp;xtra spacing to add between rows in the book list (can be negative):</string>
</property>
<property name="buddy">
<cstring>opt_book_list_extra_row_spacing</cstring>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="button_adjust_colors">
<item row="5" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Adjust &amp;colors</string>
<string>&amp;Round the corners of covers:</string>
</property>
<property name="buddy">
<cstring>opt_cover_corner_radius</cstring>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QSpinBox" name="opt_cover_corner_radius">
<property name="toolTip">
<string>Round the corners of covers in many places they are displayed such as the Cover grid, Book details panel, etc. Adjust the amount of rounding with this setting. A value of between 5 and 10 looks good with most covers sizes. Zero disables rounding and is the default.</string>
</property>
<property name="specialValueText">
<string>no rounding</string>
</property>
<property name="suffix">
<string> px</string>
</property>
</widget>
</item>
@ -393,6 +416,20 @@
<string>Cover size</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="2">
<widget class="QPushButton" name="cover_grid_larger_cover">
<property name="toolTip">
<string>Make the covers larger, maintaining current aspect ratio.</string>
</property>
<property name="text">
<string>&amp;Larger covers</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/plus.png</normaloff>:/images/plus.png</iconset>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="cover_grid_smaller_cover">
<property name="toolTip">
@ -417,10 +454,20 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="opt_cover_grid_width">
<item row="1" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Cover &amp;width: </string>
</property>
<property name="buddy">
<cstring>opt_cover_grid_width</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="opt_cover_grid_height">
<property name="toolTip">
<string>The width of displayed covers.
<string>The height of displayed covers.
A value of zero means calculate automatically.</string>
</property>
<property name="specialValueText">
@ -434,10 +481,40 @@ A value of zero means calculate automatically.</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QDoubleSpinBox" name="opt_cover_grid_height">
<item row="1" column="3" rowspan="2">
<widget class="QPushButton" name="cover_grid_reset_size">
<property name="toolTip">
<string>The height of displayed covers.
<string>Reset size to automatic</string>
</property>
<property name="text">
<string>&amp;Reset size</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="5">
<widget class="QLabel" name="cover_grid_aspect_ratio">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="4">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="opt_cover_grid_width">
<property name="toolTip">
<string>The width of displayed covers.
A value of zero means calculate automatically.</string>
</property>
<property name="specialValueText">
@ -467,83 +544,6 @@ A value of zero means calculate automatically.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Cover &amp;width: </string>
</property>
<property name="buddy">
<cstring>opt_cover_grid_width</cstring>
</property>
</widget>
</item>
<item row="4" column="0" colspan="5">
<widget class="QLabel" name="cover_grid_aspect_ratio">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="cover_grid_larger_cover">
<property name="toolTip">
<string>Make the covers larger, maintaining current aspect ratio.</string>
</property>
<property name="text">
<string>&amp;Larger covers</string>
</property>
<property name="icon">
<iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/plus.png</normaloff>:/images/plus.png</iconset>
</property>
</widget>
</item>
<item row="1" column="4">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="3" rowspan="2">
<widget class="QPushButton" name="cover_grid_reset_size">
<property name="toolTip">
<string>Reset size to automatic</string>
</property>
<property name="text">
<string>&amp;Reset size</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>&amp;Round the corners:</string>
</property>
<property name="buddy">
<cstring>opt_cover_grid_corner_radius</cstring>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QSpinBox" name="opt_cover_grid_corner_radius">
<property name="toolTip">
<string>The amount by which to round the corners of the covers when they are displayed in the Cover grid. A value of 10 looks good with typical cover sizes. Adjust to your preference. A value of zero disables rounding.</string>
</property>
<property name="specialValueText">
<string>no rounding</string>
</property>
<property name="suffix">
<string> px</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -15,6 +15,7 @@ from qt.core import (
QCursor,
QEvent,
QFont,
QGraphicsPixmapItem,
QGraphicsScene,
QGraphicsView,
QIcon,
@ -43,7 +44,7 @@ from qt.core import (
from calibre import fit_image, force_unicode, strftime
from calibre.constants import ismacos, iswindows
from calibre.ebooks import BOOK_EXTENSIONS
from calibre.gui2 import error_dialog, gprefs, pixmap_to_data, warning_dialog
from calibre.gui2 import clip_border_radius, error_dialog, gprefs, pixmap_to_data, warning_dialog
from calibre.gui2.dnd import DownloadDialog, dnd_get_files, dnd_get_image, dnd_get_local_image_and_pixmap, dnd_has_extension, dnd_has_image, image_extensions
from calibre.gui2.filename_pattern_ui import Ui_Form
from calibre.gui2.progress_indicator import ProgressIndicator as _ProgressIndicator
@ -414,7 +415,8 @@ class ImageView(QWidget, ImageDropMixin):
x = int(abs(cw - w)/2)
y = int(abs(ch - h)/2)
target = QRect(x, y, w, h)
p.drawPixmap(target, pmap)
with clip_border_radius(p, target):
p.drawPixmap(target, pmap)
if self.draw_border:
pen = QPen()
pen.setWidth(self.BORDER_WIDTH)
@ -424,8 +426,18 @@ class ImageView(QWidget, ImageDropMixin):
draw_size(p, target, ow, oh)
# }}}
# CoverView {{{
class CoverView(QGraphicsView, ImageDropMixin): # {{{
class RoundedPixmap(QGraphicsPixmapItem):
def paint(self, painter, option, widget):
painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)
target = self.boundingRect().toAlignedRect()
with clip_border_radius(painter, target):
painter.drawPixmap(target, self.pixmap())
class CoverView(QGraphicsView, ImageDropMixin):
cover_changed = pyqtSignal(object)
@ -445,7 +457,7 @@ class CoverView(QGraphicsView, ImageDropMixin): # {{{
def set_pixmap(self, pmap):
self.scene = QGraphicsScene()
self.scene.addPixmap(pmap)
self.scene.addItem(RoundedPixmap(pmap))
self.setScene(self.scene)
def set_background(self, brush=None):