diff --git a/src/calibre/gui2/actions/show_quickview.py b/src/calibre/gui2/actions/show_quickview.py index bacda8492e..d82bacdf49 100644 --- a/src/calibre/gui2/actions/show_quickview.py +++ b/src/calibre/gui2/actions/show_quickview.py @@ -164,12 +164,13 @@ class ShowQuickviewAction(InterfaceAction): if self.current_instance and not self.current_instance.is_closed: self.current_instance.refresh(idx) - def change_quickview_column(self, idx): + def change_quickview_column(self, idx, show=True): ''' Called from the column header context menu to change the QV query column ''' - self.focus_quickview() - self.current_instance.slave(idx) + if show or (self.current_instance and not self.current_instance.is_closed): + self.focus_quickview() + self.current_instance.slave(idx) def library_changed(self, db): ''' 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/tag_list_editor.py b/src/calibre/gui2/dialogs/tag_list_editor.py index 6847cf0066..e2741a16af 100644 --- a/src/calibre/gui2/dialogs/tag_list_editor.py +++ b/src/calibre/gui2/dialogs/tag_list_editor.py @@ -330,7 +330,7 @@ class TagListEditor(QDialog, Ui_TagListEditor): current_row = rows[0].row() current_col = view.column_map.index(self.category) index = view.model().index(current_row, current_col) - qv.change_quickview_column(index) + qv.change_quickview_column(index, show=False) def copy_to_clipboard(self, item): cb = QApplication.clipboard() diff --git a/src/calibre/gui2/dialogs/template_dialog.py b/src/calibre/gui2/dialogs/template_dialog.py index 217dc8bdd9..2303278d9f 100644 --- a/src/calibre/gui2/dialogs/template_dialog.py +++ b/src/calibre/gui2/dialogs/template_dialog.py @@ -9,7 +9,7 @@ import json, os, traceback from qt.core import (Qt, QDialog, QDialogButtonBox, QSyntaxHighlighter, QFont, QRegExp, QApplication, QTextCharFormat, QColor, QCursor, - QIcon, QSize, QPalette) + QIcon, QSize, QPalette, QLineEdit, QByteArray) from calibre import sanitize_file_name from calibre.constants import config_dir @@ -290,16 +290,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 +310,43 @@ 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) + # Use our own widget to get rid of elision. setTextElideMode() doesn't work + for r in range(0, len(mi)): + w = QLineEdit(tv) + w.setReadOnly(True) + tv.setCellWidget(r, 0, w) + w = QLineEdit(tv) + w.setReadOnly(True) + tv.setCellWidget(r, 1, w) # Remove help icon on title bar icon = self.windowIcon() @@ -336,8 +371,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 +396,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 +411,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 +480,20 @@ 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): + w = tv.cellWidget(r, 0) + w.setText(mi.title) + w.setCursorPosition(0) + v = SafeFormat().safe_format(txt, mi, _('EXCEPTION: '), + mi, global_vars=self.global_vars, + template_functions=self.all_functions) + w = tv.cellWidget(r, 1) + w.setText(v) + w.setCursorPosition(0) def text_cursor_changed(self): cursor = self.textbox.textCursor() @@ -472,6 +528,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 +561,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