mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-12-27 07:10:19 -05:00
Merge branch 'master' of https://github.com/cbhaley/calibre
This commit is contained in:
commit
09abf38d1e
@ -488,6 +488,8 @@ def create_defs():
|
||||
defs['book_details_note_link_icon_width'] = 1.0
|
||||
defs['tag_browser_show_category_icons'] = True
|
||||
defs['tag_browser_show_value_icons'] = True
|
||||
defs['template_editor_run_as_you_type'] = True
|
||||
defs['template_editor_show_all_selected_books'] = True
|
||||
|
||||
def migrate_tweak(tweak_name, pref_name):
|
||||
# If the tweak has been changed then leave the tweak in the file so
|
||||
|
||||
@ -212,7 +212,7 @@ class TemplateHighlighter(QSyntaxHighlighter):
|
||||
|
||||
KEYWORDS_GPM = ['if', 'then', 'else', 'elif', 'fi', 'for', 'rof',
|
||||
'separator', 'break', 'continue', 'return', 'in', 'inlist',
|
||||
'inlist_field', 'def', 'fed', 'limit']
|
||||
'inlist_field', 'def', 'fed', 'limit', 'with', 'htiw']
|
||||
|
||||
KEYWORDS_PYTHON = ['and', 'as', 'assert', 'break', 'class', 'continue', 'def',
|
||||
'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from',
|
||||
@ -581,8 +581,11 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
formatter_functions().get_builtins_and_aliases())
|
||||
|
||||
# Set up the breakpoint bar
|
||||
s = gprefs.get('template_editor_break_on_print', False)
|
||||
self.go_button.setEnabled(s)
|
||||
run_as_you_type = gprefs.get('template_editor_run_as_you_type')
|
||||
self.run_as_you_type_box.setChecked(run_as_you_type)
|
||||
self.go_button.setEnabled(not run_as_you_type)
|
||||
self.break_box.setEnabled(not run_as_you_type)
|
||||
s = gprefs.get('template_editor_enable_breakpoints', False)
|
||||
self.remove_all_button.setEnabled(s)
|
||||
self.set_all_button.setEnabled(s)
|
||||
self.toggle_button.setEnabled(s)
|
||||
@ -591,6 +594,10 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
self.break_box.setChecked(s)
|
||||
self.break_box.stateChanged.connect(self.break_box_changed)
|
||||
self.go_button.clicked.connect(self.go_button_pressed)
|
||||
self.show_all_selected_books.clicked.connect(self.show_all_selected_books_changed)
|
||||
self.run_as_you_type_box.stateChanged.connect(self.run_as_you_type_box_changed)
|
||||
self.show_all_selected_books.setChecked(gprefs.get('template_editor_show_all_selected_books'))
|
||||
self.show_all_selected_books.clicked.connect(self.show_all_selected_books_changed)
|
||||
|
||||
# Set up the display table
|
||||
self.table_column_widths = None
|
||||
@ -725,14 +732,20 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
else:
|
||||
mi = (get_model_metadata_instance(), )
|
||||
self.mi = mi
|
||||
self.setup_result_display_table()
|
||||
|
||||
def setup_result_display_table(self):
|
||||
tv = self.template_value
|
||||
mi = self.mi
|
||||
row_count = len(mi) if gprefs.get('template_editor_show_all_selected_books') else 1
|
||||
tv.clear()
|
||||
tv.setColumnCount(3)
|
||||
tv.setHorizontalHeaderLabels((_('Book title'), '', _('Template value')))
|
||||
tv.horizontalHeader().setStretchLastSection(True)
|
||||
tv.horizontalHeader().sectionResized.connect(self.table_column_resized)
|
||||
tv.setRowCount(len(mi))
|
||||
tv.setRowCount(len(mi) )
|
||||
# Set the height of the table
|
||||
h = tv.rowHeight(0) * min(len(mi), 5)
|
||||
h = tv.rowHeight(0) * min(row_count, 5)
|
||||
h += 2 * tv.frameWidth() + tv.horizontalHeader().height()
|
||||
tv.setMinimumHeight(h)
|
||||
tv.setMaximumHeight(h)
|
||||
@ -742,9 +755,9 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
else:
|
||||
tv.setColumnWidth(0, tv.fontMetrics().averageCharWidth() * 10)
|
||||
tv.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
|
||||
tv.setRowCount(len(mi))
|
||||
tv.setRowCount(row_count)
|
||||
# Use our own widget to get rid of elision. setTextElideMode() doesn't work
|
||||
for r in range(len(mi)):
|
||||
for r in range(row_count):
|
||||
w = QLineEdit(tv)
|
||||
w.setReadOnly(True)
|
||||
w.setText(mi[r].get('title', _('No title provided')))
|
||||
@ -786,15 +799,15 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
|
||||
pmi = None
|
||||
new_mi.append(pmi)
|
||||
self.set_mi(new_mi, self.fm)
|
||||
if not self.break_box.isChecked():
|
||||
if not self.run_as_you_type_box.isChecked():
|
||||
self.display_values(str(self.textbox.toPlainText()))
|
||||
|
||||
def set_waiting_message(self):
|
||||
if self.break_box.isChecked():
|
||||
for i in range(len(self.mi)):
|
||||
if not self.run_as_you_type_box.isChecked():
|
||||
for i in range(self.template_value.rowCount()):
|
||||
self.template_value.cellWidget(i, 2).setText('')
|
||||
self.template_value.cellWidget(0, 2).setText(
|
||||
_("*** Breakpoints are enabled. Waiting for the 'Go' button to be pressed"))
|
||||
_("*** Waiting for the 'Go' button to be pressed"))
|
||||
|
||||
def show_code_context_menu(self, point):
|
||||
m = self.source_code.createStandardContextMenu()
|
||||
@ -930,15 +943,40 @@ def evaluate(book, context):
|
||||
gprefs['gpm_template_editor_font_size'] = toWhat
|
||||
self.set_editor_font()
|
||||
|
||||
def run_as_you_type_box_changed(self, new_state):
|
||||
gprefs['template_editor_run_as_you_type'] = new_state != 0
|
||||
self.go_button.setEnabled(new_state == 0)
|
||||
if new_state == 0:
|
||||
self.set_waiting_message()
|
||||
self.break_box.setEnabled(True)
|
||||
enable_break_boxes = self.break_box.isChecked()
|
||||
else:
|
||||
self.break_box.setEnabled(False)
|
||||
enable_break_boxes = False
|
||||
self.display_values(str(self.textbox.toPlainText()))
|
||||
|
||||
self.remove_all_button.setEnabled(enable_break_boxes)
|
||||
self.set_all_button.setEnabled(enable_break_boxes)
|
||||
self.toggle_button.setEnabled(enable_break_boxes)
|
||||
self.breakpoint_line_box.setEnabled(enable_break_boxes)
|
||||
self.breakpoint_line_box_label.setEnabled(enable_break_boxes)
|
||||
|
||||
def break_box_changed(self, new_state):
|
||||
gprefs['template_editor_break_on_print'] = new_state != 0
|
||||
self.go_button.setEnabled(new_state != 0)
|
||||
gprefs['template_editor_enable_breakpoints'] = new_state != 0
|
||||
self.remove_all_button.setEnabled(new_state != 0)
|
||||
self.set_all_button.setEnabled(new_state != 0)
|
||||
self.toggle_button.setEnabled(new_state != 0)
|
||||
self.breakpoint_line_box.setEnabled(new_state != 0)
|
||||
self.breakpoint_line_box_label.setEnabled(new_state != 0)
|
||||
if new_state == 0:
|
||||
if gprefs['template_editor_run_as_you_type']:
|
||||
self.display_values(str(self.textbox.toPlainText()))
|
||||
else:
|
||||
self.set_waiting_message()
|
||||
|
||||
def show_all_selected_books_changed(self, new_state):
|
||||
gprefs['template_editor_show_all_selected_books'] = new_state != 0
|
||||
self.setup_result_display_table()
|
||||
if gprefs['template_editor_run_as_you_type']:
|
||||
self.display_values(str(self.textbox.toPlainText()))
|
||||
else:
|
||||
self.set_waiting_message()
|
||||
@ -1042,7 +1080,7 @@ def evaluate(book, context):
|
||||
self.last_text = cur_text
|
||||
self.highlighter.regenerate_paren_positions()
|
||||
self.text_cursor_changed()
|
||||
if not self.break_box.isChecked():
|
||||
if self.run_as_you_type_box.isChecked():
|
||||
self.display_values(cur_text)
|
||||
else:
|
||||
self.set_waiting_message()
|
||||
@ -1095,6 +1133,8 @@ def evaluate(book, context):
|
||||
w.setCursorPosition(0)
|
||||
finally:
|
||||
sys.settrace(None)
|
||||
if not gprefs.get('template_editor_show_all_selected_books', True):
|
||||
break
|
||||
|
||||
def text_cursor_changed(self):
|
||||
cursor = self.textbox.textCursor()
|
||||
|
||||
@ -206,14 +206,13 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="break_box">
|
||||
<widget class="QCheckBox" name="run_as_you_type_box">
|
||||
<property name="text">
|
||||
<string>Enable &breakpoints</string>
|
||||
<string>R&un as you type</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><p>If checked, the template evaluator will stop when it
|
||||
evaluates an expression on a double-clicked line number, opening a dialog showing
|
||||
you the value as well as all the local variables</p></string>
|
||||
<string><p>If checked then the template will be run (tested) after every
|
||||
keystroke. If unchecked then the template will be run when the "Go" button is pushed.</p></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -237,7 +236,7 @@ you the value as well as all the local variables</p></string>
|
||||
<set>Qt::ToolButtonTextBesideIcon</set>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>If 'Enable breakpoints' is checked then click this button to run your template</string>
|
||||
<string>If 'Run as you type' is not checked then click this button to run your template</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -248,6 +247,18 @@ you the value as well as all the local variables</p></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="break_box">
|
||||
<property name="text">
|
||||
<string>Enable &breakpoints</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><p>If checked, the template evaluator will stop when it
|
||||
evaluates an expression on a double-clicked line number, opening a dialog showing
|
||||
you the value as well as all the local variables</p></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="breakpoint_line_box_label">
|
||||
<property name="text">
|
||||
@ -378,17 +389,34 @@ you the value as well as all the local variables</p></string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel">
|
||||
<property name="text">
|
||||
<string>Template value:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>template_value</cstring>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The value of the template using the current book in the library view</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel">
|
||||
<property name="text">
|
||||
<string>Template value:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>template_value</cstring>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The value of the template using the currently selected book(s)
|
||||
in the library view</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="show_all_selected_books">
|
||||
<property name="text">
|
||||
<string>Show template result for all selected books</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><p>If checked then the template will be evaluated for all selected
|
||||
books. If not checked then the template will be evaluated for the first selected book. Unchecking this
|
||||
box is useful if the template uses the selected books to generate a report.</p></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="3">
|
||||
<widget class="QTableWidget" name="template_value">
|
||||
|
||||
@ -60,6 +60,7 @@ class Node:
|
||||
NODE_SWITCH = 31
|
||||
NODE_SWITCH_IF = 32
|
||||
NODE_LIST_COUNT_FIELD = 33
|
||||
NODE_WITH = 34
|
||||
|
||||
def __init__(self, line_number, name):
|
||||
self.my_line_number = line_number
|
||||
@ -74,6 +75,14 @@ class Node:
|
||||
return self.my_line_number
|
||||
|
||||
|
||||
class WithNode(Node):
|
||||
def __init__(self, line_number, book_id, block):
|
||||
Node.__init__(self, line_number, 'if ...')
|
||||
self.node_type = self.NODE_WITH
|
||||
self.book_id = book_id
|
||||
self.block = block
|
||||
|
||||
|
||||
class IfNode(Node):
|
||||
def __init__(self, line_number, condition, then_part, else_part):
|
||||
Node.__init__(self, line_number, 'if ...')
|
||||
@ -600,6 +609,20 @@ class _Parser:
|
||||
def local_call_expression(self, name, arguments):
|
||||
return LocalFunctionCallNode(self.line_number, name, arguments)
|
||||
|
||||
def with_expression(self):
|
||||
self.consume()
|
||||
line_number = self.line_number
|
||||
book_id = self.top_expr()
|
||||
if not self.token_op_is(':'):
|
||||
self.error(_("{0} statement: expected '{1}', "
|
||||
"found '{2}'").format('with', ':', self.token_text()))
|
||||
self.consume()
|
||||
block = self.expression_list()
|
||||
if not self.token_is('htiw'):
|
||||
self.error(_("'{0}' statement: missing the closing '{1}'").format('def', 'fed'))
|
||||
self.consume()
|
||||
return WithNode(line_number, book_id, block)
|
||||
|
||||
def call_expression(self, name, arguments):
|
||||
compiled_func = self.funcs[name].cached_compiled_text
|
||||
if compiled_func is None:
|
||||
@ -692,6 +715,7 @@ class _Parser:
|
||||
'continue': (lambda self: self.consume(), lambda self: ContinueNode(self.line_number)),
|
||||
'return': (lambda self: self.consume(), lambda self: ReturnNode(self.line_number, self.top_expr())),
|
||||
'def': (lambda self: None, define_function_expression),
|
||||
'with': (lambda self: None, with_expression)
|
||||
}
|
||||
|
||||
# {inlined_function_name: tuple(constraint on number of length, node builder) }
|
||||
@ -1017,6 +1041,27 @@ class _Interpreter:
|
||||
raise e
|
||||
return val
|
||||
|
||||
def do_node_with(self, prog):
|
||||
line_number = prog.line_number
|
||||
parent_book = self.parent_book
|
||||
v = None
|
||||
try:
|
||||
book_id = int(self.expr(prog.book_id))
|
||||
if self.break_reporter:
|
||||
self.break_reporter("'with': book id ", str(book_id), line_number)
|
||||
self.parent_book = self.parent.book = get_database(
|
||||
self.parent_book, 'with statement').new_api.get_proxy_metadata(book_id)
|
||||
v = self.expression_list(prog.block)
|
||||
if self.break_reporter:
|
||||
self.break_reporter("'with': block value", v, line_number)
|
||||
return v
|
||||
except (StopException, ValueError, ReturnExecuted) as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
self.error(_("Unhandled exception '{0}'").format(e), line_number)
|
||||
finally:
|
||||
self.parent_book = self.parent.book = parent_book
|
||||
|
||||
def do_node_if(self, prog):
|
||||
line_number = prog.line_number
|
||||
test_part = self.expr(prog.condition)
|
||||
@ -1608,7 +1653,8 @@ class _Interpreter:
|
||||
Node.NODE_LOCAL_FUNCTION_DEFINE: do_node_local_function_define,
|
||||
Node.NODE_LOCAL_FUNCTION_CALL: do_node_local_function_call,
|
||||
Node.NODE_LIST_COUNT_FIELD: do_node_list_count_field,
|
||||
}
|
||||
Node.NODE_WITH: do_node_with,
|
||||
}
|
||||
|
||||
def expr(self, prog):
|
||||
try:
|
||||
@ -1707,6 +1753,7 @@ class TemplateFormatter(string.Formatter):
|
||||
(r'(def|fed|continue)\b', lambda x,t: (_Parser.LEX_KEYWORD, t)),
|
||||
(r'(return|inlist|break)\b', lambda x,t: (_Parser.LEX_KEYWORD, t)),
|
||||
(r'(inlist_field)\b', lambda x,t: (_Parser.LEX_KEYWORD, t)),
|
||||
(r'(with|htiw)\b', lambda x,t: (_Parser.LEX_KEYWORD, t)),
|
||||
(r'(\|\||&&|!|{|})', lambda x,t: (_Parser.LEX_OP, t)),
|
||||
(r'[(),=;:\+\-*/&]', lambda x,t: (_Parser.LEX_OP, t)),
|
||||
(r'-?[\d\.]+', lambda x,t: (_Parser.LEX_CONST, t)),
|
||||
|
||||
@ -55,6 +55,7 @@ CASE_CHANGES = _('Case changes')
|
||||
DATE_FUNCTIONS = _('Date functions')
|
||||
DB_FUNCS = _('Database functions')
|
||||
URL_FUNCTIONS = _('URL functions')
|
||||
GUI_FUNCTIONS = __('GUI functions')
|
||||
|
||||
|
||||
# Class and method to save an untranslated copy of translated strings
|
||||
@ -1249,7 +1250,7 @@ string.
|
||||
class BuiltinApproximateFormats(BuiltinFormatterFunction):
|
||||
name = 'approximate_formats'
|
||||
arg_count = 0
|
||||
category = GET_FROM_METADATA
|
||||
category = DB_FUNCS
|
||||
def __doc__getter__(self): return translate_ffml(
|
||||
r'''
|
||||
``approximate_formats()`` -- return a comma-separated list of formats associated
|
||||
@ -1278,7 +1279,7 @@ column's value in your save/send templates.
|
||||
class BuiltinFormatsModtimes(BuiltinFormatterFunction):
|
||||
name = 'formats_modtimes'
|
||||
arg_count = 1
|
||||
category = GET_FROM_METADATA
|
||||
category = DB_FUNCS
|
||||
def __doc__getter__(self): return translate_ffml(
|
||||
r'''
|
||||
``formats_modtimes(date_format_string)`` -- return a comma-separated list of
|
||||
@ -1302,7 +1303,7 @@ that format names are always uppercase, as in EPUB.
|
||||
class BuiltinFormatsSizes(BuiltinFormatterFunction):
|
||||
name = 'formats_sizes'
|
||||
arg_count = 0
|
||||
category = GET_FROM_METADATA
|
||||
category = DB_FUNCS
|
||||
def __doc__getter__(self): return translate_ffml(
|
||||
r'''
|
||||
|
||||
@ -1323,7 +1324,7 @@ format names are always uppercase, as in EPUB.
|
||||
class BuiltinFormatsPaths(BuiltinFormatterFunction):
|
||||
name = 'formats_paths'
|
||||
arg_count = -1
|
||||
category = GET_FROM_METADATA
|
||||
category = DB_FUNCS
|
||||
def __doc__getter__(self): return translate_ffml(
|
||||
r'''
|
||||
``formats_paths([separator])`` -- return a ``separator``-separated list of
|
||||
@ -1345,7 +1346,7 @@ format names are always uppercase, as in EPUB.
|
||||
class BuiltinFormatsPathSegments(BuiltinFormatterFunction):
|
||||
name = 'formats_path_segments'
|
||||
arg_count = 5
|
||||
category = GET_FROM_METADATA
|
||||
category = DB_FUNCS
|
||||
def __doc__getter__(self): return translate_ffml(
|
||||
r'''
|
||||
``formats_path_segments(with_author, with_title, with_format, with_ext, sep)``
|
||||
@ -1775,7 +1776,7 @@ template, and use that column\'s value in your save/send templates.
|
||||
class BuiltinAnnotationCount(BuiltinFormatterFunction):
|
||||
name = 'annotation_count'
|
||||
arg_count = 0
|
||||
category = GET_FROM_METADATA
|
||||
category = DB_FUNCS
|
||||
def __doc__getter__(self): return translate_ffml(
|
||||
r'''
|
||||
``annotation_count()`` -- return the total number of annotations of all types
|
||||
@ -3649,6 +3650,116 @@ This can be useful to truncate a value.
|
||||
return pat.sub(repl, template)
|
||||
|
||||
|
||||
class BuiltinSelectedBooks(BuiltinFormatterFunction):
|
||||
name = 'selected_books'
|
||||
arg_count = 0
|
||||
category = GUI_FUNCTIONS
|
||||
def __doc__getter__(self): return translate_ffml(
|
||||
r'''
|
||||
``selected_books([sorted_by, ascending])`` -- returns a list of book ids in
|
||||
selection order for the currently selected books.
|
||||
|
||||
This function can be used only in the GUI.
|
||||
''')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, *args):
|
||||
from calibre.gui2.ui import get_gui
|
||||
g = get_gui()
|
||||
book_ids = g.current_view().get_selected_ids()
|
||||
return ', '.join([str(book_id) for book_id in book_ids])
|
||||
|
||||
|
||||
class BuiltinSortBookIds(BuiltinFormatterFunction):
|
||||
name = 'sort_book_ids'
|
||||
arg_count = -1
|
||||
category = GUI_FUNCTIONS
|
||||
def __doc__getter__(self): return translate_ffml(
|
||||
r'''
|
||||
``sort_book_ids(book_ids, sorted_by, ascending [, sorted_by, ascending]*)`` --
|
||||
returns the list of book ids sorted by the column specified by the lookup name
|
||||
in ``sorted_by`` in the order specified by ``ascending``. If ``ascending`` is
|
||||
``'1'`` then the books are sorted by the value in the 'sorted_by' column in
|
||||
ascending order, otherwise in descending order. You can have multiple pairs of
|
||||
``sorted_by, ascending``. The first pair specifies the major order.
|
||||
|
||||
This function can be used only in the GUI.
|
||||
''')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, book_ids, *args):
|
||||
from calibre.gui2.ui import get_gui
|
||||
g = get_gui()
|
||||
bids = [int(b.strip()) for b in book_ids.split(',')]
|
||||
if len(args) < 2:
|
||||
raise ValueError(_('The sort_book_ids function requires at least 3 arguments'))
|
||||
if len(args) % 2 != 0:
|
||||
raise ValueError(_('The id and direction arguments must be in pairs'))
|
||||
sort_spec = []
|
||||
for i in range(0, len(args), 2):
|
||||
sort_by = args[i]
|
||||
asc = True if args[i+1] == '1' else False
|
||||
sort_spec.append((sort_by, asc))
|
||||
bids = g.current_db.new_api.multisort(sort_spec, bids)
|
||||
return ', '.join([str(b) for b in bids])
|
||||
|
||||
|
||||
class BuiltinSelectedColumn(BuiltinFormatterFunction):
|
||||
name = 'selected_column'
|
||||
arg_count = 0
|
||||
category = GUI_FUNCTIONS
|
||||
def __doc__getter__(self): return translate_ffml(
|
||||
r'''
|
||||
``selected_column()`` -- returns the lookup name of the column containing the currently
|
||||
selected cell. It returns ``''`` if no cell is selected.
|
||||
|
||||
This function can be used only in the GUI.
|
||||
''')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals):
|
||||
from calibre.gui2.ui import get_gui
|
||||
v = get_gui().current_view()
|
||||
idx = v.currentIndex()
|
||||
if idx.isValid():
|
||||
key = v.column_map[idx.column()]
|
||||
return key
|
||||
return ''
|
||||
|
||||
|
||||
class BuiltinShowDialog(BuiltinFormatterFunction):
|
||||
name = 'show_dialog'
|
||||
arg_count = 1
|
||||
category = GUI_FUNCTIONS
|
||||
def __doc__getter__(self): return translate_ffml(
|
||||
r'''
|
||||
``show_dialog(html_or_text)`` -- show a dialog containing the html or text. The
|
||||
function returns ``'1'`` if the user presses OK, ``''`` if Cancel.
|
||||
|
||||
This function can be used only in the GUI.
|
||||
''')
|
||||
|
||||
def evaluate(self, formatter, kwargs, mi, locals, html):
|
||||
from calibre.gui2.widgets2 import Dialog, HTMLDisplay
|
||||
from qt.core import QDialog, QVBoxLayout
|
||||
|
||||
class HTMLDialog(Dialog):
|
||||
|
||||
def __init__(self, title, prefs):
|
||||
super().__init__(title, 'formatter_html_dialog', prefs=prefs)
|
||||
|
||||
def setup_ui(self):
|
||||
l = QVBoxLayout(self)
|
||||
d = self.display = HTMLDisplay()
|
||||
l.addWidget(d)
|
||||
l.addWidget(self.bb)
|
||||
|
||||
def set_html(self, tt_text):
|
||||
self.display.setHtml(tt_text)
|
||||
|
||||
db = get_database(mi, 'show_dialog')
|
||||
d = HTMLDialog(_('Template output'), db.new_api.backend.prefs)
|
||||
d.set_html(html)
|
||||
return '1' if d.exec() == QDialog.DialogCode.Accepted else ''
|
||||
|
||||
|
||||
_formatter_builtins = [
|
||||
BuiltinAdd(), BuiltinAnd(), BuiltinApproximateFormats(), BuiltinArguments(),
|
||||
BuiltinAssign(),
|
||||
@ -3677,8 +3788,10 @@ _formatter_builtins = [
|
||||
BuiltinMultiply(), BuiltinNot(), BuiltinOndevice(),
|
||||
BuiltinOr(), BuiltinPrint(), BuiltinQueryString(), BuiltinRatingToStars(),
|
||||
BuiltinRange(), BuiltinRawField(), BuiltinRawList(),
|
||||
BuiltinRe(), BuiltinReGroup(), BuiltinRound(), BuiltinSelect(), BuiltinSeriesSort(),
|
||||
BuiltinSetGlobals(), BuiltinShorten(), BuiltinStrcat(), BuiltinStrcatMax(),
|
||||
BuiltinRe(), BuiltinReGroup(), BuiltinRound(), BuiltinSelect(),
|
||||
BuiltinSelectedBooks(), BuiltinSelectedColumn(), BuiltinSeriesSort(),
|
||||
BuiltinSetGlobals(), BuiltinShorten(), BuiltinShowDialog(), BuiltinSortBookIds(),
|
||||
BuiltinStrcat(), BuiltinStrcatMax(),
|
||||
BuiltinStrcmp(), BuiltinStrcmpcase(), BuiltinStrInList(), BuiltinStrlen(), BuiltinSubitems(),
|
||||
BuiltinSublist(),BuiltinSubstr(), BuiltinSubtract(), BuiltinSwapAroundArticles(),
|
||||
BuiltinSwapAroundComma(), BuiltinSwitch(), BuiltinSwitchIf(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user