mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
8c92e3e9b8
@ -60,10 +60,11 @@ from qt.core import (
|
|||||||
from calibre import fit_image, human_readable, prepare_string_for_xml
|
from calibre import fit_image, human_readable, prepare_string_for_xml
|
||||||
from calibre.constants import DEBUG, config_dir, islinux
|
from calibre.constants import DEBUG, config_dir, islinux
|
||||||
from calibre.ebooks.metadata import fmt_sidx, rating_to_stars
|
from calibre.ebooks.metadata import fmt_sidx, rating_to_stars
|
||||||
from calibre.gui2 import clip_border_radius, config, empty_index, gprefs, rating_font
|
from calibre.gui2 import clip_border_radius, config, empty_index, gprefs, rating_font, is_dark_theme
|
||||||
from calibre.gui2.dnd import path_from_qurl
|
from calibre.gui2.dnd import path_from_qurl
|
||||||
from calibre.gui2.gestures import GestureManager
|
from calibre.gui2.gestures import GestureManager
|
||||||
from calibre.gui2.library.caches import CoverCache, ThumbnailCache
|
from calibre.gui2.library.caches import CoverCache, ThumbnailCache
|
||||||
|
from calibre.gui2.library.models import themed_icon_name
|
||||||
from calibre.gui2.pin_columns import PinContainer
|
from calibre.gui2.pin_columns import PinContainer
|
||||||
from calibre.utils import join_with_timeout
|
from calibre.utils import join_with_timeout
|
||||||
from calibre.utils.config import prefs, tweaks
|
from calibre.utils.config import prefs, tweaks
|
||||||
@ -554,7 +555,12 @@ class CoverDelegate(QStyledItemDelegate):
|
|||||||
elif name == ':ondevice':
|
elif name == ':ondevice':
|
||||||
ans = QIcon.ic('ok.png').pixmap(sz, sz)
|
ans = QIcon.ic('ok.png').pixmap(sz, sz)
|
||||||
elif name:
|
elif name:
|
||||||
pmap = QIcon(os.path.join(config_dir, 'cc_icons', name)).pixmap(sz, sz)
|
pmap = None
|
||||||
|
d = themed_icon_name(os.path.join(config_dir, 'cc_icons'), name)
|
||||||
|
if d is not None:
|
||||||
|
pmap = QIcon(d).pixmap(sz, sz)
|
||||||
|
if pmap is None:
|
||||||
|
pmap = QIcon(os.path.join(config_dir, 'cc_icons', name)).pixmap(sz, sz)
|
||||||
if not pmap.isNull():
|
if not pmap.isNull():
|
||||||
ans = pmap
|
ans = pmap
|
||||||
cache[name] = ans
|
cache[name] = ans
|
||||||
|
@ -23,7 +23,7 @@ from calibre.db.search import CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH, _match
|
|||||||
from calibre.db.utils import force_to_bool
|
from calibre.db.utils import force_to_bool
|
||||||
from calibre.ebooks.metadata import authors_to_string, fmt_sidx, string_to_authors
|
from calibre.ebooks.metadata import authors_to_string, fmt_sidx, string_to_authors
|
||||||
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
||||||
from calibre.gui2 import error_dialog, simple_excepthook
|
from calibre.gui2 import error_dialog, simple_excepthook, is_dark_theme
|
||||||
from calibre.gui2.library import DEFAULT_SORT
|
from calibre.gui2.library import DEFAULT_SORT
|
||||||
from calibre.library.coloring import color_row_key
|
from calibre.library.coloring import color_row_key
|
||||||
from calibre.library.save_to_disk import find_plugboard
|
from calibre.library.save_to_disk import find_plugboard
|
||||||
@ -93,6 +93,20 @@ class ColumnColor: # {{{
|
|||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
|
||||||
|
def themed_icon_name(icon_dir, icon_name):
|
||||||
|
root,ext = os.path.splitext(icon_name)
|
||||||
|
# Remove any theme from the icon name
|
||||||
|
root = root.removesuffix('-for-dark-theme').removesuffix('-for-light-theme')
|
||||||
|
# Check if the correct themed icon exists.
|
||||||
|
theme_suffix = '-for-dark-theme' if is_dark_theme() else '-for-light-theme'
|
||||||
|
d = os.path.join(icon_dir, root + theme_suffix + ext)
|
||||||
|
if os.path.exists(d):
|
||||||
|
return d
|
||||||
|
# No themed icon exists. Try the original name
|
||||||
|
d = os.path.join(icon_dir, icon_name)
|
||||||
|
return d if os.path.exists(d) else None
|
||||||
|
|
||||||
|
|
||||||
class ColumnIcon: # {{{
|
class ColumnIcon: # {{{
|
||||||
|
|
||||||
def __init__(self, formatter, model):
|
def __init__(self, formatter, model):
|
||||||
@ -132,9 +146,10 @@ class ColumnIcon: # {{{
|
|||||||
total_width = 0
|
total_width = 0
|
||||||
rh = max(2, self.model.row_height - 4)
|
rh = max(2, self.model.row_height - 4)
|
||||||
dim = int(self.dpr * rh)
|
dim = int(self.dpr * rh)
|
||||||
|
icon_dir = os.path.join(config_dir, 'cc_icons')
|
||||||
for icon in icons:
|
for icon in icons:
|
||||||
d = os.path.join(config_dir, 'cc_icons', icon)
|
d = themed_icon_name(icon_dir, icon)
|
||||||
if (os.path.exists(d)):
|
if d is not None:
|
||||||
bm = QPixmap(d)
|
bm = QPixmap(d)
|
||||||
scaled, nw, nh = fit_image(bm.width(), bm.height(), bm.width(), dim)
|
scaled, nw, nh = fit_image(bm.width(), bm.height(), bm.width(), dim)
|
||||||
bm = bm.scaled(int(nw), int(nh), aspectRatioMode=Qt.AspectRatioMode.IgnoreAspectRatio,
|
bm = bm.scaled(int(nw), int(nh), aspectRatioMode=Qt.AspectRatioMode.IgnoreAspectRatio,
|
||||||
|
@ -21,6 +21,7 @@ from qt.core import (
|
|||||||
QDoubleValidator,
|
QDoubleValidator,
|
||||||
QFrame,
|
QFrame,
|
||||||
QGridLayout,
|
QGridLayout,
|
||||||
|
QHBoxLayout,
|
||||||
QIcon,
|
QIcon,
|
||||||
QIntValidator,
|
QIntValidator,
|
||||||
QItemSelection,
|
QItemSelection,
|
||||||
@ -47,7 +48,8 @@ from qt.core import (
|
|||||||
|
|
||||||
from calibre import as_unicode, prepare_string_for_xml, sanitize_file_name
|
from calibre import as_unicode, prepare_string_for_xml, sanitize_file_name
|
||||||
from calibre.constants import config_dir
|
from calibre.constants import config_dir
|
||||||
from calibre.gui2 import choose_files, choose_save_file, error_dialog, gprefs, open_local_file, pixmap_to_data, question_dialog
|
from calibre.gui2 import (choose_files, choose_save_file, error_dialog, gprefs, info_dialog,
|
||||||
|
open_local_file, pixmap_to_data, question_dialog)
|
||||||
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
from calibre.gui2.dialogs.template_dialog import TemplateDialog
|
||||||
from calibre.gui2.metadata.single_download import RichTextDelegate
|
from calibre.gui2.metadata.single_download import RichTextDelegate
|
||||||
from calibre.gui2.preferences import ListViewWithMoveByKeyPress
|
from calibre.gui2.preferences import ListViewWithMoveByKeyPress
|
||||||
@ -512,11 +514,19 @@ class RuleEditor(QDialog): # {{{
|
|||||||
' blanking all of its boxes'))
|
' blanking all of its boxes'))
|
||||||
l.addWidget(l6, 8, 0, 1, 8)
|
l.addWidget(l6, 8, 0, 1, 8)
|
||||||
|
|
||||||
|
bbl = QHBoxLayout()
|
||||||
self.bb = bb = QDialogButtonBox(
|
self.bb = bb = QDialogButtonBox(
|
||||||
QDialogButtonBox.StandardButton.Ok|QDialogButtonBox.StandardButton.Cancel)
|
QDialogButtonBox.StandardButton.Ok|QDialogButtonBox.StandardButton.Cancel)
|
||||||
bb.accepted.connect(self.accept)
|
bb.accepted.connect(self.accept)
|
||||||
bb.rejected.connect(self.reject)
|
bb.rejected.connect(self.reject)
|
||||||
l.addWidget(bb, 9, 0, 1, 8)
|
if self.rule_kind in ('emblem', 'icon'):
|
||||||
|
theme_button = QPushButton(_('Using icons in light/dark themes'))
|
||||||
|
theme_button.setIcon(QIcon.ic('help.png'))
|
||||||
|
theme_button.clicked.connect(self.show_theme_help)
|
||||||
|
bbl.addWidget(theme_button)
|
||||||
|
bbl.addStretch(10)
|
||||||
|
bbl.addWidget(bb)
|
||||||
|
l.addLayout(bbl, 9, 0, 1, 8)
|
||||||
if self.rule_kind != 'color':
|
if self.rule_kind != 'color':
|
||||||
self.remove_button = b = bb.addButton(_('&Remove icons'), QDialogButtonBox.ButtonRole.ActionRole)
|
self.remove_button = b = bb.addButton(_('&Remove icons'), QDialogButtonBox.ButtonRole.ActionRole)
|
||||||
b.setIcon(QIcon.ic('minus.png'))
|
b.setIcon(QIcon.ic('minus.png'))
|
||||||
@ -555,6 +565,30 @@ class RuleEditor(QDialog): # {{{
|
|||||||
|
|
||||||
self.resize(self.sizeHint())
|
self.resize(self.sizeHint())
|
||||||
|
|
||||||
|
def show_theme_help(self):
|
||||||
|
msg = '<p>'+ _(
|
||||||
|
'You can use different icons in light and dark themes. To do this, '
|
||||||
|
'add two icons to the icon list. One of the icons must have either the '
|
||||||
|
'"plain" name, for example "ok.png", or the themed name, for example '
|
||||||
|
'"ok-for-light-theme.png". The other icon must have a themed name with '
|
||||||
|
'the same prefix, for example "ok-for-dark-theme.png". '
|
||||||
|
'</p><p>'
|
||||||
|
'Example: if the light theme icon is named "ok.png" then the dark '
|
||||||
|
'theme icon must be named "ok-for-dark-theme.png". If the light '
|
||||||
|
'theme icon is named "ok-for-light-theme.png" then the dark theme '
|
||||||
|
'icon must be named either ok.png or "ok-for-dark-theme.png".'
|
||||||
|
'</p><p>'
|
||||||
|
'When defining a rule, use either of the icon names. The correct '
|
||||||
|
'icon for the theme will automatically be used, if it exists.'
|
||||||
|
'</p><p>'
|
||||||
|
'You are not required to change existing rules to use theming. Decide '
|
||||||
|
'the theme where the existing icon should be used then add the '
|
||||||
|
'other icon with the correct themed name. '
|
||||||
|
'</p><p>'
|
||||||
|
'Remember to add both the light and dark theme icons to the list of icons.'
|
||||||
|
) + '</p>'
|
||||||
|
info_dialog(self, _('Using icons in light/dark themes'), msg, show=True)
|
||||||
|
|
||||||
def multiple_box_clicked(self):
|
def multiple_box_clicked(self):
|
||||||
self.update_filename_box()
|
self.update_filename_box()
|
||||||
self.update_icon_filenames_in_box()
|
self.update_icon_filenames_in_box()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user