This commit is contained in:
Kovid Goyal 2025-05-11 19:50:04 +05:30
commit a1a611cd1a
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 72 additions and 12 deletions

View File

@ -149,17 +149,32 @@ class Plugin: # {{{
from calibre.gui2 import gprefs
class ConfigDialog(QDialog):
def __init__(self, parent, config_widget):
super().__init__(parent)
self.config_widget = config_widget
def accept(self):
if ((validate := getattr(self.config_widget, 'validate', None)) and
getattr(self.config_widget, 'validate_before_accept', False)):
if not validate():
return
super().accept()
try:
config_widget = self.config_widget()
except NotImplementedError:
config_widget = None
prefname = 'plugin config dialog:'+self.type + ':' + self.name
config_dialog = QDialog(parent)
config_dialog = ConfigDialog(parent, config_widget)
button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
v = QVBoxLayout(config_dialog)
button_box.accepted.connect(config_dialog.accept)
button_box.rejected.connect(config_dialog.reject)
config_dialog.setWindowTitle(_('Customize') + ' ' + self.name)
try:
config_widget = self.config_widget()
except NotImplementedError:
config_widget = None
if isinstance(config_widget, tuple):
from calibre.gui2 import warning_dialog

View File

@ -54,11 +54,13 @@ class KOBOTOUCHConfig(TabbedDeviceConfig):
def __init__(self, device_settings, all_formats, supports_subdirs,
must_read_metadata, supports_use_author_sort,
extra_customization_message, device, extra_customization_choices=None, parent=None):
extra_customization_message, device, extra_customization_choices=None,
parent=None):
super().__init__(device_settings, all_formats, supports_subdirs,
must_read_metadata, supports_use_author_sort,
extra_customization_message, device, extra_customization_choices, parent)
extra_customization_message, device, extra_customization_choices, parent,
validate_before_accept=True)
self.device_settings = device_settings
self.all_formats = all_formats
@ -88,6 +90,7 @@ class KOBOTOUCHConfig(TabbedDeviceConfig):
def validate(self):
validated = super().validate()
validated &= self.tab2.validate()
validated &= self.tab1.validate()
return validated
@property
@ -193,6 +196,12 @@ class Tab1Config(DeviceConfigTab): # {{{
self.addDeviceWidget(self.book_uploads_options)
self.l.addStretch()
def validate(self):
v = self.collections_options.validate()
v &= self.book_uploads_options.validate()
return v
# }}}
@ -364,6 +373,7 @@ class BookUploadsGroupBox(DeviceOptionsGroupBox):
self.template_la = la = QLabel('\xa0\xa0' + _('Template to decide conversion:'))
self.kepubify_template_edit = TemplateConfig(
self.kepubify_checkbox.text(),
device.get_pref('template_for_kepubify'),
tooltip='<p>' + _(
'Enter a template to decide if an EPUB book is to be auto converted to KEPUB. '
@ -399,6 +409,9 @@ class BookUploadsGroupBox(DeviceOptionsGroupBox):
def update_template_state(self):
self.kepubify_template_edit.setEnabled(self.kepubify)
def validate(self):
return self.kepubify_template_edit.validate()
@property
def override_kobo_replace_existing(self):
return self.override_kobo_replace_existing_checkbox.isChecked()
@ -518,6 +531,7 @@ class CollectionsGroupBox(DeviceOptionsGroupBox):
device.get_pref('use_collections_template')
)
self.collections_template_edit = TemplateConfig(
self.use_collections_template_checkbox.text(),
device.get_pref('collections_template'),
tooltip=_("Enter a template to generate collections."
" The result of the template will be combined with the values from Collections column."
@ -559,6 +573,27 @@ class CollectionsGroupBox(DeviceOptionsGroupBox):
self.use_collections_columns_checkbox_clicked(device.get_pref('use_collections_columns'))
self.use_collections_template_checkbox_clicked(device.get_pref('use_collections_template'))
def validate(self):
v = self.validate_collections_columns()
v &= self.collections_template_edit.validate()
return v
def validate_collections_columns(self):
from calibre.gui2.ui import get_gui
db = get_gui().current_db
fm = db.field_metadata
bad_names = []
for l in [v.strip() for v in self.collections_columns.split(',') if v.strip()]:
if l not in fm.keys():
bad_names.append(l)
if bad_names:
s = ', '.join(bad_names)
error_dialog(self, _('Kobo configuration: Invalid collection column names'),
'<p>'+_("Collection column names that don't exist in the library: {0}").format(s),
show=True)
return False
return True
def use_collections_columns_checkbox_clicked(self, checked):
self.collections_columns_edit.setEnabled(checked)
@ -872,6 +907,7 @@ class MetadataGroupBox(DeviceOptionsGroupBox):
device.get_pref('update_subtitle')
)
self.subtitle_template_edit = TemplateConfig(
self.update_subtitle_checkbox.text(),
device.get_pref('subtitle_template'),
tooltip=_('Enter a template to use to set the subtitle. '
'If the template is empty, the subtitle will be cleared.'
@ -883,6 +919,7 @@ class MetadataGroupBox(DeviceOptionsGroupBox):
device.get_pref('update_bookstats')
)
self.bookstats_wordcount_template_edit = TemplateConfig(
self.update_bookstats_checkbox.text(),
device.get_pref('bookstats_wordcount_template'),
label=_('Words:'),
tooltip=_('Enter a template to use to set the word count for the book. '
@ -890,6 +927,7 @@ class MetadataGroupBox(DeviceOptionsGroupBox):
)
)
self.bookstats_pagecount_template_edit = TemplateConfig(
_('Pages'),
device.get_pref('bookstats_pagecount_template'),
label=_('Pages:'),
tooltip=_('Enter a template to use to set the page count for the book. '
@ -899,6 +937,7 @@ class MetadataGroupBox(DeviceOptionsGroupBox):
self.bookstats_timetoread_label = QLabel(_('Hours to read estimates:'))
self.bookstats_timetoread_upper_template_edit = TemplateConfig(
_('Upper estimate'),
device.get_pref('bookstats_timetoread_upper_template'),
label=_('Upper:'),
tooltip=_('Enter a template to use to set the upper estimate of the time to read for the book. '
@ -907,6 +946,7 @@ class MetadataGroupBox(DeviceOptionsGroupBox):
)
)
self.bookstats_timetoread_lower_template_edit = TemplateConfig(
_('Lower estimate'),
device.get_pref('bookstats_timetoread_lower_template'),
label=_('Lower:'),
tooltip=_('Enter a template to use to set the lower estimate of the time to read for the book. '
@ -1042,8 +1082,9 @@ class MetadataGroupBox(DeviceOptionsGroupBox):
class TemplateConfig(QWidget): # {{{
def __init__(self, val, label=None, tooltip=None):
def __init__(self, name, val, label=None, tooltip=None):
super().__init__()
self.name = name
self.l = l = QGridLayout(self)
self.setLayout(l)
col = 0
@ -1080,10 +1121,10 @@ class TemplateConfig(QWidget): # {{{
tmpl = self.template
try:
validation_formatter.validate(tmpl)
v = validation_formatter.validate(tmpl)
return True
except Exception as err:
error_dialog(self, _('Invalid template'),
error_dialog(self, _('Invalid template for {0}').format(self.name),
'<p>'+_('The template "%s" is invalid:')%tmpl +
'<br>'+str(err), show=True)

View File

@ -63,15 +63,19 @@ class TabbedDeviceConfig(QTabWidget):
DeviceConfigTab, for each set of options. Within the tabs, group boxes, subclassed
from DeviceOptionsGroupBox, are created to further group the options. The group
boxes can be coded to support any control type and dependencies between them.
Set validate_before_accept to True if you want validation() to be called
when OK is pressed
'''
def __init__(self, device_settings, all_formats, supports_subdirs,
must_read_metadata, supports_use_author_sort,
extra_customization_message, device,
extra_customization_choices=None, parent=None):
extra_customization_choices=None, parent=None, validate_before_accept = False):
QTabWidget.__init__(self, parent)
self._device = weakref.ref(device)
self.validate_before_accept = validate_before_accept
self.device_settings = device_settings
self.all_formats = set(all_formats)
self.supports_subdirs = supports_subdirs

View File

@ -2035,7 +2035,7 @@ class ValidateFormatter(TemplateFormatter):
def validate(self, x):
from calibre.ebooks.metadata.book.base import Metadata
return self.safe_format(x, {}, 'VALIDATE ERROR', Metadata(''))
return self.unsafe_format(x, {}, 'VALIDATE ERROR', Metadata(''))
validation_formatter = ValidateFormatter()