Wire up the color palette preferences into the main preferences GUI

This commit is contained in:
Kovid Goyal 2024-02-05 12:03:56 +05:30
parent 95c28f6ab4
commit bdc000d2ec
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 194 additions and 176 deletions

View File

@ -1144,7 +1144,7 @@ class Application(QApplication):
self.file_event_hook = None
if override_program_name:
args = [override_program_name] + args[1:]
self.palette_manager = PaletteManager(gprefs['color_palette'], gprefs['ui_style'], force_calibre_style, headless)
self.palette_manager = PaletteManager(force_calibre_style, headless)
if headless:
args.extend(('-platformpluginpath', plugins_loc, '-platform', 'headless'))
else:

View File

@ -2,10 +2,11 @@
# License: GPLv3 Copyright: 2024, Kovid Goyal <kovid at kovidgoyal.net>
import textwrap
from contextlib import suppress
from qt.core import (
QCheckBox, QDialog, QDialogButtonBox, QHBoxLayout, QLabel, QPalette, QScrollArea,
QSize, QSizePolicy, QTabWidget, QVBoxLayout, QWidget, pyqtSignal,
QCheckBox, QComboBox, QDialog, QHBoxLayout, QIcon, QLabel, QPalette, QPushButton,
QScrollArea, QSize, QSizePolicy, QTabWidget, QVBoxLayout, QWidget, pyqtSignal,
)
from calibre.gui2 import Application, gprefs
@ -121,7 +122,8 @@ class PaletteWidget(QWidget):
self.mode_name = mode_name
self.mode_title = {'dark': _('dark'), 'light': _('light')}[mode_name]
self.l = l = QVBoxLayout(self)
self.la = la = QLabel(_('These colors will be used for the calibre interface when calibre is in "{}" mode').format(self.mode_title))
self.la = la = QLabel(_('These colors will be used for the calibre interface when calibre is in "{}" mode.'
' You can adjust individual colors below by enabling the "Use a custom color scheme" setting.').format(self.mode_title))
l.addWidget(la)
la.setWordWrap(True)
self.use_custom = uc = QCheckBox(_('Use a &custom color scheme'))
@ -164,18 +166,38 @@ class PaletteConfig(Dialog):
def setup_ui(self):
self.l = l = QVBoxLayout(self)
h = QHBoxLayout()
self.la = la = QLabel(_('Color &palette'))
self.palette = p = QComboBox(self)
p.addItem(_('System default'), 'system')
p.addItem(_('Light'), 'light')
p.addItem(_('Dark'), 'dark')
idx = p.findData(gprefs['color_palette'])
p.setCurrentIndex(idx)
la.setBuddy(p)
h.addWidget(la), h.addWidget(p)
tt = textwrap.fill(_(
'The style of colors to use, either light or dark. By default, the system setting for light/dark is used.'
' This means that calibre will change from light to dark and vice versa as the system changes colors.'
))
la.setToolTip(tt), p.setToolTip(tt)
l.addLayout(h)
self.tabs = tabs = QTabWidget(self)
l.addWidget(tabs)
self.light_tab = lt = PaletteWidget(parent=self)
tabs.addTab(lt, _('&Light mode colors'))
self.dark_tab = dt = PaletteWidget('dark', parent=self)
tabs.addTab(dt, _('&Dark mode colors'))
l.addWidget(self.bb)
b = self.bb.addButton(_('Restore &defaults'), QDialogButtonBox.ButtonRole.ActionRole)
h = QHBoxLayout()
self.rd = b = QPushButton(QIcon.ic('clear_left.png'), _('Restore &defaults'))
b.clicked.connect(self.restore_defaults)
h.addWidget(b), h.addStretch(10), h.addWidget(self.bb)
l.addLayout(h)
def apply_settings(self):
with gprefs:
gprefs['color_palette'] = str(self.palette.currentData())
self.light_tab.apply_settings()
self.dark_tab.apply_settings()
Application.instance().palette_manager.refresh_palette()

View File

@ -215,13 +215,14 @@ standard_pixmaps = { # {{{
class PaletteManager(QObject):
color_palette: str
has_fixed_palette: bool
using_calibre_style: bool
is_dark_theme: bool
def __init__(self, color_palette, ui_style, force_calibre_style, headless):
def __init__(self, force_calibre_style, headless):
from calibre.gui2 import gprefs
super().__init__()
self.color_palette = color_palette
self.color_palette = gprefs['color_palette']
ui_style = gprefs['ui_style']
self.is_dark_theme = False
self.ignore_palette_changes = False
@ -232,13 +233,12 @@ class PaletteManager(QObject):
self.using_calibre_style = ui_style != 'system'
else:
self.using_calibre_style = os.environ.get('CALIBRE_USE_SYSTEM_THEME', '0') == '0'
self.has_fixed_palette = self.color_palette != 'system' and self.using_calibre_style
args = []
self.args_to_qt = tuple(args)
if ismacos and not headless and self.has_fixed_palette:
if ismacos and not headless:
from calibre_extensions.cocoa import set_appearance
set_appearance(color_palette)
set_appearance(self.color_palette)
def initialize(self):
app = QApplication.instance()
@ -252,23 +252,9 @@ class PaletteManager(QObject):
app = QApplication.instance()
system_is_dark = app.styleHints().colorScheme() == Qt.ColorScheme.Dark
app.styleHints().colorSchemeChanged.connect(self.color_scheme_changed)
if iswindows:
use_dark_palette = self.color_palette == 'dark' or (self.color_palette == 'system' and system_is_dark)
elif ismacos:
use_dark_palette = self.color_palette == 'dark'
else:
use_dark_palette = self.color_palette == 'dark' or (self.color_palette == 'system' and system_is_dark)
if use_dark_palette:
self.set_dark_mode_palette()
else:
self.set_light_mode_palette()
if self.has_fixed_palette and (self.color_palette == 'dark') != QApplication.instance().palette().is_dark_theme():
if self.color_palette == 'dark':
self.set_dark_mode_palette()
else:
self.set_light_mode_palette()
if self.has_fixed_palette:
QApplication.instance().setAttribute(Qt.ApplicationAttribute.AA_SetPalette, True)
use_dark_palette = self.color_palette == 'dark' or (self.color_palette == 'system' and system_is_dark)
self.set_dark_mode_palette() if use_dark_palette else self.set_light_mode_palette()
QApplication.instance().setAttribute(Qt.ApplicationAttribute.AA_SetPalette, True)
if DEBUG:
print('Using calibre Qt style:', self.using_calibre_style, file=sys.stderr)
@ -354,7 +340,7 @@ QTabBar::tab:only-one {
def color_scheme_changed(self, new_color_scheme):
if DEBUG:
print('System Color Scheme changed to:', new_color_scheme, file=sys.stderr)
if self.has_fixed_palette:
if self.color_palette != 'system' or not self.using_calibre_style:
return
if new_color_scheme == Qt.ColorScheme.Dark:
self.set_dark_mode_palette()
@ -384,7 +370,7 @@ QTabBar::tab:only-one {
else:
if DEBUG:
print('ApplicationPaletteChange event received', file=sys.stderr)
if self.has_fixed_palette:
if self.using_calibre_style:
pal = dark_palette() if self.color_palette == 'dark' else light_palette()
if QApplication.instance().palette().color(QPalette.ColorRole.Window) != pal.color(QPalette.ColorRole.Window):
if DEBUG:
@ -393,7 +379,13 @@ QTabBar::tab:only-one {
self.on_palette_change()
def refresh_palette(self):
is_dark = QApplication.instance().palette().is_dark_theme()
from calibre.gui2 import gprefs
self.color_palette = gprefs['color_palette']
if ismacos:
from calibre_extensions.cocoa import set_appearance
set_appearance(self.color_palette)
system_is_dark = QApplication.instance().styleHints().colorScheme() == Qt.ColorScheme.Dark
is_dark = self.color_palette == 'dark' or (self.color_palette == 'system' and system_is_dark)
pal = dark_palette() if is_dark else light_palette()
self.set_palette(pal)
self.on_palette_change()

View File

@ -580,7 +580,6 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.default_author_link = DefaultAuthorLink(self.default_author_link_container)
self.default_author_link.changed_signal.connect(self.changed_signal)
r('ui_style', gprefs, restart_required=True, choices=[(_('System default'), 'system'), (_('calibre style'), 'calibre')])
r('color_palette', gprefs, restart_required=True, choices=[(_('System default'), 'system'), (_('Light'), 'light'), (_('Dark'), 'dark')])
r('book_list_tooltips', gprefs)
r('dnd_merge', gprefs)
r('wrap_toolbar_text', gprefs, restart_required=True)
@ -840,6 +839,14 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
self.opt_gui_layout.addItem(_('Narrow'), 'narrow')
self.opt_gui_layout.currentIndexChanged.connect(self.changed_signal)
set_help_tips(self.opt_gui_layout, config.help('gui_layout'))
self.button_adjust_colors.clicked.connect(self.adjust_colors)
def adjust_colors(self):
from calibre.gui2.dialogs.palette import PaletteConfig
d = PaletteConfig(self)
if d.exec() == QDialog.DialogCode.Accepted:
d.apply_settings()
self.changed_signal.emit()
def initial_tab_changed(self):
self.sections_view.setCurrentRow(self.tabWidget.currentIndex())
@ -907,8 +914,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
def update_color_palette_state(self):
if self.ui_style_available:
enabled = self.opt_ui_style.currentData() == 'calibre'
self.opt_color_palette.setEnabled(enabled)
self.opt_color_palette_label.setEnabled(enabled)
self.button_adjust_colors.setEnabled(enabled)
def export_layout(self, model=None):
filename = choose_save_file(self, 'em_import_export_field_list',

View File

@ -28,38 +28,53 @@
<string>&amp;Main interface</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_9">
<item row="7" column="1">
<widget class="QCheckBox" name="opt_show_layout_buttons">
<item row="11" column="0">
<widget class="QCheckBox" name="opt_row_numbers_in_book_list">
<property name="text">
<string>Show &amp;layout buttons in the status bar</string>
<string>Show &amp;row numbers in the book list</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="opt_systray_icon">
<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">
<string>Enable s&amp;ystem tray icon (needs restart)</string>
<string>User interface &amp;colors:</string>
</property>
<property name="buddy">
<cstring>button_adjust_colors</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="icon_theme">
<item row="3" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string/>
<string>&amp;User interface layout:</string>
</property>
<property name="buddy">
<cstring>opt_gui_layout</cstring>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QPushButton" name="change_font_button">
<item row="0" column="0">
<widget class="QLabel" name="label_widget_style">
<property name="text">
<string>Change &amp;font (needs restart)</string>
<string>User interface style (&amp;needs restart):</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="icon_theme_button">
<property name="text">
<string>Change &amp;icon theme</string>
<property name="buddy">
<cstring>opt_ui_style</cstring>
</property>
</widget>
</item>
@ -73,50 +88,24 @@
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="opt_show_splash_screen">
<item row="5" column="0">
<widget class="QCheckBox" name="opt_systray_icon">
<property name="text">
<string>Show the &amp;splash screen at startup</string>
<string>Enable s&amp;ystem tray icon (needs restart)</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="opt_language">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
<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="minimumContentsLength">
<number>20</number>
<property name="text">
<string>Disable &amp;animations</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="opt_gui_layout">
<property name="maximumSize">
<size>
<width>250</width>
<height>16777215</height>
</size>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property>
<property name="minimumContentsLength">
<number>20</number>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QSpinBox" name="opt_book_list_extra_row_spacing">
<property name="suffix">
<string> px</string>
</property>
<property name="minimum">
<number>-20</number>
</property>
</widget>
</item>
<item row="0" column="1">
<item row="0" column="2">
<widget class="QComboBox" name="opt_ui_style"/>
</item>
<item row="8" column="0">
@ -140,71 +129,28 @@
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_17">
<item row="8" column="2">
<widget class="QPushButton" name="change_font_button">
<property name="text">
<string>&amp;User interface layout:</string>
</property>
<property name="buddy">
<cstring>opt_gui_layout</cstring>
<string>Change &amp;font (needs restart)</string>
</property>
</widget>
</item>
<item row="12" column="0" colspan="2">
<widget class="QCheckBox" name="opt_booklist_grid">
<item row="7" column="0">
<widget class="QCheckBox" name="opt_book_list_tooltips">
<property name="text">
<string>Draw a &amp;grid in the book list</string>
<string>Show &amp;tooltips in the book list</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_widget_style">
<item row="1" column="0">
<widget class="QLabel" name="icon_theme">
<property name="text">
<string>User interface style (&amp;needs restart):</string>
</property>
<property name="buddy">
<cstring>opt_ui_style</cstring>
<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="5" column="1">
<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">
<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="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="9" column="0" colspan="2">
<item row="9" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Toolbar</string>
@ -246,13 +192,19 @@
</layout>
</widget>
</item>
<item row="6" 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>
<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="text">
<string>Disable n&amp;otifications on job completion</string>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
</property>
<property name="minimumContentsLength">
<number>20</number>
</property>
</widget>
</item>
@ -266,29 +218,75 @@
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="opt_book_list_tooltips">
<item row="1" column="2">
<widget class="QPushButton" name="icon_theme_button">
<property name="text">
<string>Show &amp;tooltips in the book list</string>
<string>Change &amp;icon theme</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="opt_color_palette_label">
<property name="text">
<string>Color &amp;palette (needs restart):</string>
<item row="10" column="2">
<widget class="QSpinBox" name="opt_book_list_extra_row_spacing">
<property name="suffix">
<string> px</string>
</property>
<property name="buddy">
<cstring>opt_color_palette</cstring>
<property name="minimum">
<number>-20</number>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="opt_color_palette">
<item row="13" 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">
<widget class="QCheckBox" name="opt_disable_tray_notification">
<property name="toolTip">
<string>&lt;p&gt;The colors to use for the calibre interface. By default the system colors are used. You can change this to force a light or dark color scheme. Note that if this is not set to system default then if the system wide color scheme is changed calibre will not follow it.
&lt;p&gt;Also, if you set the calibre &lt;i&gt;User interface style&lt;/i&gt; to &lt;i&gt;System default&lt;/i&gt;, then this setting will not take effect and system colors will always be used.</string>
<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>
</property>
<property name="text">
<string>Disable n&amp;otifications on job completion</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="12" 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="2" column="2">
<widget class="QPushButton" name="button_adjust_colors">
<property name="text">
<string>Adjust &amp;colors</string>
</property>
</widget>
</item>
@ -821,8 +819,8 @@ A value of zero means calculate automatically.</string>
<widget class="QLabel" name="label_3">
<property name="text">
<string>&lt;p&gt;Note: &lt;b&gt;comments&lt;/b&gt;-like columns will always
be displayed at the end unless their "Heading position" is
"Show heading to the side".&lt;/p&gt;</string>
be displayed at the end unless their &quot;Heading position&quot; is
&quot;Show heading to the side&quot;.&lt;/p&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
@ -1294,12 +1292,12 @@ structure and you want to use the same column order for each one.&lt;/p&gt;</str
<layout class="QGridLayout" name="gridlayout_22">
<item row="0" column="0">
<widget class="QCheckBox" name="opt_show_avg_rating">
<property name="text">
<string>Show &amp;average ratings</string>
</property>
<property name="toolTip">
<string>Show the average rating per item indication in the Tag browser</string>
</property>
<property name="text">
<string>Show &amp;average ratings</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
@ -1307,12 +1305,12 @@ structure and you want to use the same column order for each one.&lt;/p&gt;</str
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="opt_show_links_in_tag_browser">
<property name="text">
<string>Show &amp;links icons</string>
</property>
<property name="toolTip">
<string>Show an icon if the item has an attached link</string>
</property>
<property name="text">
<string>Show &amp;links icons</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
@ -1339,12 +1337,12 @@ see the counts by hovering your mouse over any item.&lt;/p&gt;</string>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="opt_show_notes_in_tag_browser">
<property name="text">
<string>Show &amp;notes icons</string>
</property>
<property name="toolTip">
<string>Show an icon if the item has an attached note</string>
</property>
<property name="text">
<string>Show &amp;notes icons</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
@ -1372,14 +1370,14 @@ box will cause these empty categories to be hidden.&lt;/p&gt;</string>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="opt_icons_on_right_in_tag_browser">
<property name="text">
<string>Place icons on the &amp;right, in columns</string>
</property>
<property name="toolTip">
<string>If checked the notes and links icons will be placed at the right, after
the count and in columns. If unchecked, the icons will be placed immediately after the text,
to the left of the count and not in columns.</string>
</property>
<property name="text">
<string>Place icons on the &amp;right, in columns</string>
</property>
<property name="checked">
<bool>true</bool>
</property>