mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Three changes to template processing:
1) If the user presses ESC, ask "are you sure" if the template has changed. 2) Fix syntax highlighting of comments 3) Improve the python template example in the template docs, better using the new_api.
This commit is contained in:
parent
3e4ee63f2b
commit
9b68f5c89a
@ -677,10 +677,17 @@ Here is an example of a PTM template that produces a list of all the authors for
|
||||
def evaluate(book, context):
|
||||
if book.series is None:
|
||||
return ''
|
||||
db = context.db.new_api
|
||||
ans = set()
|
||||
db = context.db
|
||||
for id_ in db.search_getting_ids(f'series:"={book.series}"', ''):
|
||||
ans.update(v.strip() for v in db.new_api.field_for('author_sort', id_).split('&'))
|
||||
# Get the list of books in the series
|
||||
ids = db.search(f'series:"={book.series}"', '')
|
||||
if ids:
|
||||
# Get all the author_sort values for the books in the series
|
||||
author_sorts = (v for v in db.all_field_for('author_sort', ids).values())
|
||||
# Add the names to the result set, removing duplicates
|
||||
for aus in author_sorts:
|
||||
ans.update(v.strip() for v in aus.split('&'))
|
||||
# Make a sorted comma-separated string from the result set
|
||||
return ', '.join(v.replace(',', ';') for v in sorted(ans))
|
||||
|
||||
The output in :guilabel:`Book details` looks like this:
|
||||
|
@ -18,7 +18,8 @@ from calibre import sanitize_file_name
|
||||
from calibre.constants import config_dir
|
||||
from calibre.ebooks.metadata.book.base import Metadata
|
||||
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
||||
from calibre.gui2 import gprefs, error_dialog, choose_files, choose_save_file, pixmap_to_data
|
||||
from calibre.gui2 import (gprefs, error_dialog, choose_files, choose_save_file,
|
||||
pixmap_to_data, question_dialog)
|
||||
from calibre.gui2.dialogs.template_dialog_ui import Ui_TemplateDialog
|
||||
from calibre.library.coloring import (displayable_columns, color_row_key)
|
||||
from calibre.utils.config_base import tweaks
|
||||
@ -84,45 +85,30 @@ class TemplateHighlighter(QSyntaxHighlighter):
|
||||
r.append((re.compile(a), b))
|
||||
|
||||
if not for_python:
|
||||
a(
|
||||
r"\b[a-zA-Z]\w*\b(?!\(|\s+\()"
|
||||
r"|\$+#?[a-zA-Z]\w*",
|
||||
"identifier")
|
||||
|
||||
a(r"\b[a-zA-Z]\w*\b(?!\(|\s+\()"
|
||||
r"|\$+#?[a-zA-Z]\w*",
|
||||
"identifier")
|
||||
a(r"^program:", "keymode")
|
||||
a(
|
||||
"|".join([r"\b%s\b" % keyword for keyword in self.KEYWORDS_GPM]),
|
||||
"keyword")
|
||||
|
||||
a(
|
||||
"|".join([r"\b%s\b" % builtin for builtin in
|
||||
a("|".join([r"\b%s\b" % keyword for keyword in self.KEYWORDS_GPM]), "keyword")
|
||||
a("|".join([r"\b%s\b" % builtin for builtin in
|
||||
(builtin_functions if builtin_functions else
|
||||
formatter_functions().get_builtins())]),
|
||||
"builtin")
|
||||
|
||||
a(r"""(?<!:)'[^']*'|"[^"]*\"""", "string")
|
||||
else:
|
||||
a(r"^python:", "keymode")
|
||||
|
||||
a(
|
||||
"|".join([r"\b%s\b" % keyword for keyword in self.KEYWORDS_PYTHON]),
|
||||
"keyword")
|
||||
a(
|
||||
"|".join([r"\b%s\b" % builtin for builtin in self.BUILTINS_PYTHON]),
|
||||
"builtin")
|
||||
a(
|
||||
"|".join([r"\b%s\b" % constant for constant in self.CONSTANTS_PYTHON]),
|
||||
"constant")
|
||||
|
||||
a("|".join([r"\b%s\b" % keyword for keyword in self.KEYWORDS_PYTHON]), "keyword")
|
||||
a("|".join([r"\b%s\b" % builtin for builtin in self.BUILTINS_PYTHON]), "builtin")
|
||||
a("|".join([r"\b%s\b" % constant for constant in self.CONSTANTS_PYTHON]), "constant")
|
||||
a(r"\bPyQt6\b|\bqt.core\b|\bQt?[A-Z][a-z]\w+\b", "pyqt")
|
||||
a(r"@\w+(\.\w+)?\b", "decorator")
|
||||
|
||||
a(r"""('|").*?\1""", "string")
|
||||
stringRe = r"""((?:"|'){3}).*?\1"""
|
||||
a(stringRe, "string")
|
||||
self.stringRe = re.compile(stringRe)
|
||||
self.tripleSingleRe = re.compile(r"""'''(?!")""")
|
||||
self.tripleDoubleRe = re.compile(r'''"""(?!')''')
|
||||
a(r'#[^\n]*', "comment")
|
||||
a(
|
||||
r"\b[+-]?[0-9]+[lL]?\b"
|
||||
r"|\b[+-]?0[xX][0-9A-Fa-f]+[lL]?\b"
|
||||
@ -197,17 +183,6 @@ class TemplateHighlighter(QSyntaxHighlighter):
|
||||
elif text[0] == "#":
|
||||
self.setFormat(0, textLength, self.Formats["comment"])
|
||||
return
|
||||
elif self.for_python:
|
||||
stack = []
|
||||
for i, c in enumerate(text):
|
||||
if c in ('"', "'"):
|
||||
if stack and stack[-1] == c:
|
||||
stack.pop()
|
||||
else:
|
||||
stack.append(c)
|
||||
elif c == "#" and len(stack) == 0:
|
||||
self.setFormat(i, len(text), self.Formats["comment"])
|
||||
return
|
||||
|
||||
for regex, format_ in self.Rules:
|
||||
for m in regex.finditer(text):
|
||||
@ -430,6 +405,8 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
self.textbox.setPlainText(text)
|
||||
else:
|
||||
text = ''
|
||||
self.original_text = text
|
||||
|
||||
self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText(_('&OK'))
|
||||
self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setText(_('&Cancel'))
|
||||
|
||||
@ -852,6 +829,16 @@ def evaluate(book, context):
|
||||
gprefs['template_editor_table_widths'] = self.table_column_widths
|
||||
gprefs['template_editor_dialog_geometry'] = bytearray(self.saveGeometry())
|
||||
|
||||
def keyPressEvent(self, ev):
|
||||
if ev.key() == Qt.Key.Key_Escape:
|
||||
# Check about ESC to avoid killing the dialog by mistake
|
||||
if self.textbox.toPlainText() != self.original_text:
|
||||
r = question_dialog(self, _('Discard changes?'),
|
||||
_('Do you really want to close this dialog, discarding any changes?'))
|
||||
if not r:
|
||||
return
|
||||
QDialog.keyPressEvent(self, ev)
|
||||
|
||||
def accept(self):
|
||||
txt = str(self.textbox.toPlainText()).rstrip()
|
||||
if (self.coloring or self.iconing or self.embleming) and not txt:
|
||||
|
Loading…
x
Reference in New Issue
Block a user