mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Merge branch 'master' of https://github.com/cbhaley/calibre
Fixes #1920592 [[Enhancement - Category editor] Searching in library automatically opens the Quickview](https://bugs.launchpad.net/calibre/+bug/1920592) Fixes #1920576 [Enhancement Request: Template tester: Next/last book](https://bugs.launchpad.net/calibre/+bug/1920576)
This commit is contained in:
commit
d9c69a4ccc
@ -164,10 +164,11 @@ class ShowQuickviewAction(InterfaceAction):
|
|||||||
if self.current_instance and not self.current_instance.is_closed:
|
if self.current_instance and not self.current_instance.is_closed:
|
||||||
self.current_instance.refresh(idx)
|
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
|
Called from the column header context menu to change the QV query column
|
||||||
'''
|
'''
|
||||||
|
if show or (self.current_instance and not self.current_instance.is_closed):
|
||||||
self.focus_quickview()
|
self.focus_quickview()
|
||||||
self.current_instance.slave(idx)
|
self.current_instance.slave(idx)
|
||||||
|
|
||||||
|
@ -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'),
|
|
||||||
_('Only one book can be selected'), show=True)
|
|
||||||
|
|
||||||
index = rows[0]
|
|
||||||
if index.isValid():
|
|
||||||
db = view.model().db
|
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,
|
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]
|
||||||
|
@ -330,7 +330,7 @@ class TagListEditor(QDialog, Ui_TagListEditor):
|
|||||||
current_row = rows[0].row()
|
current_row = rows[0].row()
|
||||||
current_col = view.column_map.index(self.category)
|
current_col = view.column_map.index(self.category)
|
||||||
index = view.model().index(current_row, current_col)
|
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):
|
def copy_to_clipboard(self, item):
|
||||||
cb = QApplication.clipboard()
|
cb = QApplication.clipboard()
|
||||||
|
@ -9,7 +9,7 @@ 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, QLineEdit, 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 +290,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 +310,43 @@ 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)
|
||||||
|
# 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
|
# Remove help icon on title bar
|
||||||
icon = self.windowIcon()
|
icon = self.windowIcon()
|
||||||
@ -336,8 +371,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 +396,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 +411,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 +480,20 @@ 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):
|
||||||
|
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):
|
def text_cursor_changed(self):
|
||||||
cursor = self.textbox.textCursor()
|
cursor = self.textbox.textCursor()
|
||||||
@ -472,6 +528,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 +561,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):
|
||||||
|
@ -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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user