diff --git a/src/calibre/gui2/dialogs/template_dialog.py b/src/calibre/gui2/dialogs/template_dialog.py index 1ca8d08797..05b96a946f 100644 --- a/src/calibre/gui2/dialogs/template_dialog.py +++ b/src/calibre/gui2/dialogs/template_dialog.py @@ -488,7 +488,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): icon_field_key=None, icon_rule_kind=None, doing_emblem=False, text_is_placeholder=False, dialog_is_st_editor=False, global_vars=None, all_functions=None, builtin_functions=None, - python_context_object=None, dialog_number=None, + python_context_object=None, dialog_number=None, kwargs=None, formatter=SafeFormat, icon_dir='cc_icons'): # If dialog_number isn't None then we want separate non-modal windows # that don't stay on top of the main dialog. This lets Alt-Tab work to @@ -517,6 +517,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): self.dialog_is_st_editor = dialog_is_st_editor self.global_vars = global_vars or {} self.python_context_object = python_context_object or PythonTemplateContext() + self.kwargs = kwargs cols = [] self.fm = fm @@ -779,7 +780,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): tb.setIcon(QIcon.ic('edit_input.png')) tb.setToolTip(_('Open Edit metadata on this book')) tb.clicked.connect(partial(self.metadata_button_clicked, r)) - tb.setEnabled(mi[r].get('id', -1) >= 0) + tb.setEnabled(int(mi[r].get('id', -1)) >= 0) tv.setCellWidget(r, 1, tb) w = QLineEdit(tv) w.setReadOnly(True) @@ -1092,12 +1093,11 @@ def evaluate(book, context): else: sys.settrace(None) try: - v = self.formatter().safe_format(txt, mi, _('EXCEPTION:'), - mi, global_vars=self.global_vars, + v = self.formatter().safe_format(txt, self.kwargs[r] if self.kwargs is not None else mi, + _('EXCEPTION:'), mi, global_vars=self.global_vars, template_functions=self.all_functions, break_reporter=self.break_reporter if r == break_on_mi else None, - python_context_object=self.python_context_object, - database=db) + python_context_object=self.python_context_object, database=db) w = tv.cellWidget(r, 2) w.setText(v.translate(translate_table)) w.setCursorPosition(0) diff --git a/src/calibre/gui2/preferences/save_template.py b/src/calibre/gui2/preferences/save_template.py index ba51d2bd74..cb6d2195a4 100644 --- a/src/calibre/gui2/preferences/save_template.py +++ b/src/calibre/gui2/preferences/save_template.py @@ -10,7 +10,7 @@ from qt.core import QWidget, pyqtSignal from calibre.gui2 import error_dialog, question_dialog from calibre.gui2.dialogs.template_dialog import TemplateDialog from calibre.gui2.preferences.save_template_ui import Ui_Form -from calibre.library.save_to_disk import FORMAT_ARG_DESCS, preprocess_template +from calibre.library.save_to_disk import FORMAT_ARG_DESCS, Formatter, get_component_metadata, preprocess_template from calibre.utils.formatter import validation_formatter @@ -26,10 +26,14 @@ class SaveTemplate(QWidget, Ui_Form): def initialize(self, name, default, help, field_metadata): variables = sorted(FORMAT_ARG_DESCS.keys()) + help_text = self.orig_help_text if name == 'send_to_device': - self.help_label.setText(self.orig_help_text + ' ' + _( + help_text = help_text + ' ' + _( 'This setting can be overridden for individual devices,' - ' by clicking the device icon and choosing "Configure this device".')) + ' by clicking the device icon and choosing "Configure this device".') + self.help_label.setText(help_text + ' ' + + _('Title and series will have articles moved to the end unless ' + 'you change the tweak "{}"').format('save_template_title_series_sorting')) rows = [] for var in variables: rows.append(f'
' + self.opt_timefmt.toolTip() + '
' + + _('Changes will not appear in the template editor until you press the apply button.') + '
') self.save_template.blockSignals(False) def restore_defaults(self): diff --git a/src/calibre/gui2/preferences/sending.py b/src/calibre/gui2/preferences/sending.py index 14df6ce7b2..0484c697c1 100644 --- a/src/calibre/gui2/preferences/sending.py +++ b/src/calibre/gui2/preferences/sending.py @@ -43,6 +43,9 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form): self.send_template.initialize('send_to_device', self.proxy['send_template'], self.proxy.help('send_template'), self.gui.library_view.model().db.field_metadata) + self.opt_send_timefmt.setToolTip('' + self.opt_send_timefmt.toolTip() + '
' + + _('Changes will not appear in the template editor until you press the apply button.') + '
') + self.send_template.blockSignals(False) def restore_defaults(self): diff --git a/src/calibre/library/save_to_disk.py b/src/calibre/library/save_to_disk.py index d6be25aae7..36440ba8d5 100644 --- a/src/calibre/library/save_to_disk.py +++ b/src/calibre/library/save_to_disk.py @@ -172,10 +172,7 @@ class Formatter(TemplateFormatter): return key -def get_components(template, mi, id, timefmt='%b %Y', length=250, - sanitize_func=ascii_filename, replace_whitespace=False, - to_lowercase=False, safe_format=True, last_has_extension=True, - single_dir=False): +def get_component_metadata(template, mi, id_, timefmt='%b %Y'): tsorder = tweaks['save_template_title_series_sorting'] format_args = FORMAT_ARGS.copy() format_args.update(mi.all_non_none_fields()) @@ -201,8 +198,6 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250, format_args['series'] = title_sort(mi.series, order=tsorder) if mi.series_index is not None: format_args['series_index'] = mi.format_series_index() - else: - template = re.sub(r'\{series_index[^}]*?\}', '', template) if mi.rating is not None: format_args['rating'] = mi.format_rating(divide_by=2.0) if mi.identifiers: @@ -214,11 +209,13 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250, format_args['timestamp'] = strftime(timefmt, mi.timestamp.timetuple()) if not is_date_undefined(mi.pubdate) and hasattr(mi.pubdate, 'timetuple'): format_args['pubdate'] = strftime(timefmt, mi.pubdate.timetuple()) + else: + format_args.pop('pubdate', None) if (hasattr(mi, 'last_modified') and not is_date_undefined(mi.last_modified) and hasattr(mi.last_modified, 'timetuple')): format_args['last_modified'] = strftime(timefmt, mi.last_modified.timetuple()) - format_args['id'] = str(id) + format_args['id'] = str(id_) # Now format the custom fields custom_metadata = mi.get_all_user_metadata(make_copy=False) for key in custom_metadata: @@ -240,6 +237,13 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250, format_args[key] = str(format_args[key]) else: format_args[key] = '' + return format_args + +def get_components(template, mi, id_, timefmt='%b %Y', length=250, + sanitize_func=ascii_filename, replace_whitespace=False, + to_lowercase=False, safe_format=True, last_has_extension=True, + single_dir=False): + format_args = get_component_metadata(template, mi, id_, timefmt) if safe_format: components = Formatter().safe_format(template, format_args, 'G_C-EXCEPTION!', mi)