Enhancement #1920576: Template tester: Next/last book.

Instead of next/last, the template tester now shows the template values for selected books. Also now remembers geometry.
This commit is contained in:
Charles Haley 2021-03-20 13:54:54 +00:00
parent 222cbf5e0d
commit f92ca6190a
3 changed files with 83 additions and 33 deletions

View File

@ -36,16 +36,14 @@ class ShowTemplateTesterAction(InterfaceAction):
if not rows: if not rows:
return error_dialog(self.gui, _('No books selected'), return error_dialog(self.gui, _('No books selected'),
_('One book must be selected'), show=True) _('One book must be selected'), show=True)
if len(rows) > 1: mi = []
return error_dialog(self.gui, _('Selected multiple books'), db = view.model().db
_('Only one book can be selected'), show=True) for row in rows:
if row.isValid():
index = rows[0] mi.append(db.new_api.get_proxy_metadata(db.data.index_to_id(row.row())))
if index.isValid(): if mi:
db = view.model().db
t = TemplateDialog(self.gui, self.previous_text, t = TemplateDialog(self.gui, self.previous_text,
mi=db.get_metadata(index.row(), index_is_id=False, get_cover=False), mi, text_is_placeholder=self.first_time)
text_is_placeholder=self.first_time)
t.setWindowTitle(_('Template tester')) t.setWindowTitle(_('Template tester'))
if t.exec_() == QDialog.DialogCode.Accepted: if t.exec_() == QDialog.DialogCode.Accepted:
self.previous_text = t.rule[1] self.previous_text = t.rule[1]

View File

@ -9,7 +9,8 @@ import json, os, traceback
from qt.core import (Qt, QDialog, QDialogButtonBox, QSyntaxHighlighter, QFont, from qt.core import (Qt, QDialog, QDialogButtonBox, QSyntaxHighlighter, QFont,
QRegExp, QApplication, QTextCharFormat, QColor, QCursor, QRegExp, QApplication, QTextCharFormat, QColor, QCursor,
QIcon, QSize, QPalette) QIcon, QSize, QPalette, QTableWidgetItem, QStyledItemDelegate,
QByteArray)
from calibre import sanitize_file_name from calibre import sanitize_file_name
from calibre.constants import config_dir from calibre.constants import config_dir
@ -290,16 +291,18 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.template_name.setVisible(False) self.template_name.setVisible(False)
if mi: if mi:
if not isinstance(mi, list):
mi = (mi, )
self.mi = mi self.mi = mi
else: else:
self.mi = Metadata(_('Title'), [_('Author')]) mi = Metadata(_('Title'), [_('Author')])
self.mi.author_sort = _('Author Sort') mi.author_sort = _('Author Sort')
self.mi.series = ngettext('Series', 'Series', 1) mi.series = ngettext('Series', 'Series', 1)
self.mi.series_index = 3 mi.series_index = 3
self.mi.rating = 4.0 mi.rating = 4.0
self.mi.tags = [_('Tag 1'), _('Tag 2')] mi.tags = [_('Tag 1'), _('Tag 2')]
self.mi.languages = ['eng'] mi.languages = ['eng']
self.mi.id = 1 mi.id = 1
if fm is not None: if fm is not None:
self.mi.set_all_user_metadata(fm.custom_field_metadata()) self.mi.set_all_user_metadata(fm.custom_field_metadata())
else: else:
@ -308,10 +311,35 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
# the columns will all be empty, which in some very unusual # the columns will all be empty, which in some very unusual
# cases might cause formatter errors. We can live with that. # cases might cause formatter errors. We can live with that.
from calibre.gui2.ui import get_gui from calibre.gui2.ui import get_gui
self.mi.set_all_user_metadata( mi.set_all_user_metadata(
get_gui().current_db.new_api.field_metadata.custom_field_metadata()) get_gui().current_db.new_api.field_metadata.custom_field_metadata())
for col in self.mi.get_all_user_metadata(False): for col in mi.get_all_user_metadata(False):
self.mi.set(col, (col,), 0) mi.set(col, (col,), 0)
mi = [mi,]
# Set up the display table
self.table_column_widths = None
try:
self.table_column_widths = \
gprefs.get('template_editor_table_widths', None)
except:
pass
tv = self.template_value
tv.setRowCount(len(mi))
tv.setColumnCount(2)
tv.setHorizontalHeaderLabels((_('Book title'), _('Template value')))
tv.horizontalHeader().setStretchLastSection(True)
tv.horizontalHeader().sectionResized.connect(self.table_column_resized)
# Set the height of the table
h = tv.rowHeight(0) * min(len(mi), 5)
h += 2 * tv.frameWidth() + tv.horizontalHeader().height()
tv.setMinimumHeight(h);
tv.setMaximumHeight(h);
# Set the size of the title column
if self.table_column_widths:
tv.setColumnWidth(0, self.table_column_widths[0])
else:
tv.setColumnWidth(0, tv.fontMetrics().averageCharWidth() * 10)
# Remove help icon on title bar # Remove help icon on title bar
icon = self.windowIcon() icon = self.windowIcon()
@ -336,8 +364,11 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
if text_is_placeholder: if text_is_placeholder:
self.textbox.setPlaceholderText(text) self.textbox.setPlaceholderText(text)
self.textbox.clear() self.textbox.clear()
text = ''
else: else:
self.textbox.setPlainText(text) self.textbox.setPlainText(text)
else:
text = ''
self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText(_('&OK')) self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText(_('&OK'))
self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setText(_('&Cancel')) self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setText(_('&Cancel'))
self.color_copy_button.clicked.connect(self.color_to_clipboard) self.color_copy_button.clicked.connect(self.color_to_clipboard)
@ -358,7 +389,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.function_type_string(f, longform=False)), f) self.function_type_string(f, longform=False)), f)
self.function.setCurrentIndex(0) self.function.setCurrentIndex(0)
self.function.currentIndexChanged.connect(self.function_changed) self.function.currentIndexChanged.connect(self.function_changed)
self.textbox_changed() self.display_values(text)
self.rule = (None, '') self.rule = (None, '')
tt = _('Template language tutorial') tt = _('Template language tutorial')
@ -373,6 +404,14 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.font_size_box.setValue(gprefs['gpm_template_editor_font_size']) self.font_size_box.setValue(gprefs['gpm_template_editor_font_size'])
self.font_size_box.valueChanged.connect(self.font_size_changed) self.font_size_box.valueChanged.connect(self.font_size_changed)
self.textbox.setFocus() self.textbox.setFocus()
# Now geometry
try:
geom = gprefs.get('template_editor_dialog_geometry', None)
if geom is not None:
QApplication.instance().safe_restore_geometry(self, QByteArray(geom))
except:
pass
def font_size_changed(self, toWhat): def font_size_changed(self, toWhat):
gprefs['gpm_template_editor_font_size'] = toWhat gprefs['gpm_template_editor_font_size'] = toWhat
@ -434,10 +473,16 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.last_text = cur_text self.last_text = cur_text
self.highlighter.regenerate_paren_positions() self.highlighter.regenerate_paren_positions()
self.text_cursor_changed() self.text_cursor_changed()
self.template_value.setText( self.display_values(cur_text)
SafeFormat().safe_format(cur_text, self.mi, _('EXCEPTION: '),
self.mi, global_vars=self.global_vars, def display_values(self, txt):
template_functions=self.all_functions)) tv = self.template_value
for r,mi in enumerate(self.mi):
tv.setItem(r, 0, QTableWidgetItem(mi.title))
v = SafeFormat().safe_format(txt, mi, _('EXCEPTION: '),
mi, global_vars=self.global_vars,
template_functions=self.all_functions)
tv.setItem(r, 1, QTableWidgetItem(v))
def text_cursor_changed(self): def text_cursor_changed(self):
cursor = self.textbox.textCursor() cursor = self.textbox.textCursor()
@ -472,6 +517,15 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.source_code.setPlainText(self.all_functions[name].program_text) self.source_code.setPlainText(self.all_functions[name].program_text)
self.func_type.setText(self.function_type_string(name, longform=True)) self.func_type.setText(self.function_type_string(name, longform=True))
def table_column_resized(self, col, old, new):
self.table_column_widths = []
for c in range(0, self.template_value.columnCount()):
self.table_column_widths.append(self.template_value.columnWidth(c))
def save_geometry(self):
gprefs['template_editor_table_widths'] = self.table_column_widths
gprefs['template_editor_dialog_geometry'] = bytearray(self.saveGeometry())
def accept(self): def accept(self):
txt = unicode_type(self.textbox.toPlainText()).rstrip() txt = unicode_type(self.textbox.toPlainText()).rstrip()
if self.coloring: if self.coloring:
@ -496,6 +550,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog):
self.rule = ('icon', 'title', txt) self.rule = ('icon', 'title', txt)
else: else:
self.rule = ('', txt) self.rule = ('', txt)
self.save_geometry()
QDialog.accept(self) QDialog.accept(self)
def reject(self): def reject(self):

View File

@ -183,7 +183,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="2" column="0" colspan="4">
<widget class="QPlainTextEdit" name="textbox"> <widget class="QPlainTextEdit" name="textbox">
<property name="toolTip"> <property name="toolTip">
<string>The template program text</string> <string>The template program text</string>
@ -223,11 +223,8 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="6" column="0" colspan="4">
<widget class="QLineEdit" name="template_value"> <widget class="QTableWidget" name="template_value">
<property name="readOnly">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item row="11" column="0"> <item row="11" column="0">
@ -420,7 +417,7 @@
</item> </item>
</layout> </layout>
</item> </item>
<item row="21" column="0" colspan="5"> <item row="21" column="0" colspan="4">
<widget class="QFrame"> <widget class="QFrame">
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::HLine</enum> <enum>QFrame::HLine</enum>