diff --git a/src/calibre/gui2/actions/show_template_tester.py b/src/calibre/gui2/actions/show_template_tester.py index abe33b3570..3060ad4a21 100644 --- a/src/calibre/gui2/actions/show_template_tester.py +++ b/src/calibre/gui2/actions/show_template_tester.py @@ -36,16 +36,14 @@ class ShowTemplateTesterAction(InterfaceAction): if not rows: return error_dialog(self.gui, _('No books selected'), _('One book must be selected'), show=True) - if len(rows) > 1: - return error_dialog(self.gui, _('Selected multiple books'), - _('Only one book can be selected'), show=True) - - index = rows[0] - if index.isValid(): - db = view.model().db + mi = [] + db = view.model().db + for row in rows: + if row.isValid(): + mi.append(db.new_api.get_proxy_metadata(db.data.index_to_id(row.row()))) + if mi: t = TemplateDialog(self.gui, self.previous_text, - mi=db.get_metadata(index.row(), index_is_id=False, get_cover=False), - text_is_placeholder=self.first_time) + mi, text_is_placeholder=self.first_time) t.setWindowTitle(_('Template tester')) if t.exec_() == QDialog.DialogCode.Accepted: self.previous_text = t.rule[1] diff --git a/src/calibre/gui2/dialogs/template_dialog.py b/src/calibre/gui2/dialogs/template_dialog.py index 217dc8bdd9..ef8095ba1f 100644 --- a/src/calibre/gui2/dialogs/template_dialog.py +++ b/src/calibre/gui2/dialogs/template_dialog.py @@ -9,7 +9,8 @@ import json, os, traceback from qt.core import (Qt, QDialog, QDialogButtonBox, QSyntaxHighlighter, QFont, QRegExp, QApplication, QTextCharFormat, QColor, QCursor, - QIcon, QSize, QPalette) + QIcon, QSize, QPalette, QTableWidgetItem, QStyledItemDelegate, + QByteArray) from calibre import sanitize_file_name from calibre.constants import config_dir @@ -290,16 +291,18 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): self.template_name.setVisible(False) if mi: + if not isinstance(mi, list): + mi = (mi, ) self.mi = mi else: - self.mi = Metadata(_('Title'), [_('Author')]) - self.mi.author_sort = _('Author Sort') - self.mi.series = ngettext('Series', 'Series', 1) - self.mi.series_index = 3 - self.mi.rating = 4.0 - self.mi.tags = [_('Tag 1'), _('Tag 2')] - self.mi.languages = ['eng'] - self.mi.id = 1 + mi = Metadata(_('Title'), [_('Author')]) + mi.author_sort = _('Author Sort') + mi.series = ngettext('Series', 'Series', 1) + mi.series_index = 3 + mi.rating = 4.0 + mi.tags = [_('Tag 1'), _('Tag 2')] + mi.languages = ['eng'] + mi.id = 1 if fm is not None: self.mi.set_all_user_metadata(fm.custom_field_metadata()) else: @@ -308,10 +311,35 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): # the columns will all be empty, which in some very unusual # cases might cause formatter errors. We can live with that. 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()) - for col in self.mi.get_all_user_metadata(False): - self.mi.set(col, (col,), 0) + for col in mi.get_all_user_metadata(False): + 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 icon = self.windowIcon() @@ -336,8 +364,11 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): if text_is_placeholder: self.textbox.setPlaceholderText(text) self.textbox.clear() + text = '' else: self.textbox.setPlainText(text) + else: + text = '' self.buttonBox.button(QDialogButtonBox.StandardButton.Ok).setText(_('&OK')) self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setText(_('&Cancel')) 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.setCurrentIndex(0) self.function.currentIndexChanged.connect(self.function_changed) - self.textbox_changed() + self.display_values(text) self.rule = (None, '') 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.valueChanged.connect(self.font_size_changed) 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): gprefs['gpm_template_editor_font_size'] = toWhat @@ -434,10 +473,16 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): self.last_text = cur_text self.highlighter.regenerate_paren_positions() self.text_cursor_changed() - self.template_value.setText( - SafeFormat().safe_format(cur_text, self.mi, _('EXCEPTION: '), - self.mi, global_vars=self.global_vars, - template_functions=self.all_functions)) + self.display_values(cur_text) + + def display_values(self, txt): + 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): cursor = self.textbox.textCursor() @@ -472,6 +517,15 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): self.source_code.setPlainText(self.all_functions[name].program_text) 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): txt = unicode_type(self.textbox.toPlainText()).rstrip() if self.coloring: @@ -496,6 +550,7 @@ class TemplateDialog(QDialog, Ui_TemplateDialog): self.rule = ('icon', 'title', txt) else: self.rule = ('', txt) + self.save_geometry() QDialog.accept(self) def reject(self): diff --git a/src/calibre/gui2/dialogs/template_dialog.ui b/src/calibre/gui2/dialogs/template_dialog.ui index 8c12c20c87..06a116dd5d 100644 --- a/src/calibre/gui2/dialogs/template_dialog.ui +++ b/src/calibre/gui2/dialogs/template_dialog.ui @@ -183,7 +183,7 @@ - + The template program text @@ -223,11 +223,8 @@ - - - - true - + + @@ -420,7 +417,7 @@ - + QFrame::HLine