diff --git a/src/calibre/gui2/fts/cards.py b/src/calibre/gui2/fts/cards.py
index 8df3425d0e..543a401db3 100644
--- a/src/calibre/gui2/fts/cards.py
+++ b/src/calibre/gui2/fts/cards.py
@@ -23,6 +23,7 @@ from qt.core import (
QTextDocument,
QTimer,
QUrl,
+ QVariant,
QVBoxLayout,
QWidget,
pyqtSignal,
@@ -32,7 +33,7 @@ from calibre import prepare_string_for_xml
from calibre.db.cache import Cache
from calibre.ebooks.metadata import authors_to_string, fmt_sidx
from calibre.gui2 import config
-from calibre.gui2.fts.utils import get_db
+from calibre.gui2.fts.utils import get_db, jump_shortcut
from calibre.gui2.widgets import BusyCursor
from calibre.utils.img import resize_to_fit
@@ -69,6 +70,42 @@ def default_cover():
return ic.pixmap(ic.availableSizes()[0]).toImage()
+@lru_cache(maxsize=8)
+def icon_resource_provider(qurl: QUrl) -> QVariant:
+ if qurl.scheme() == 'calibre-icon':
+ ic = QIcon.cached_icon(qurl.path().lstrip('/'))
+ if ic.is_ok():
+ dpr = QApplication.instance().devicePixelRatio()
+ pmap = ic.pixmap(ic.availableSizes()[0])
+ sz = QSizeF(16 * dpr, 16 * dpr).toSize()
+ pmap = pmap.scaled(sz, transformMode=Qt.TransformationMode.SmoothTransformation)
+ pmap.setDevicePixelRatio(dpr)
+ return pmap
+ return QVariant()
+
+
+@lru_cache(maxsize=256)
+def button_line(book_id: int, has_book: bool) -> str:
+ template = (
+ f''
+ '\xa0{text}\xa0\xa0\xa0'
+ )
+ if has_book:
+ li = template.format(which='reindex', icon='view-refresh.png', text=_('Re-index'), tt=_(
+ 'Re-index this book. Useful if the book has been changed outside of calibre, and thus not automatically re-indexed.'))
+ else:
+ li = template.format(which='unindex', icon='trash.png', text=_('Un-index'), tt=_(
+ 'This book has been deleted from the library but is still present in the'
+ ' full text search index. Remove it.'))
+ return (
+ template.format(which='jump', icon='lt.png', text=_('Select'), tt=_(
+ 'Scroll to this book in the calibre library book list and select it [{}]').format(jump_shortcut())) +
+ template.format(which='mark', icon='marked.png', text=_('Mark'), tt=_(
+ 'Put a pin on this book in the calibre library, for future reference.\n'
+ 'You can search for marked books using the search term: {0}').format('marked:true')) +
+ li)
+
+
class CardData:
_height: int = -1
@@ -133,9 +170,11 @@ class CardData:
{prepare_string_for_xml(self.results.title)}
{prepare_string_for_xml(authors_to_string(self.results.authors))}
{series}
+{button_line(self.results.book_id, self.results.book_in_db)}
'''
doc = QTextDocument()
doc.setDocumentMargin(0)
+ doc.setResourceProvider(icon_resource_provider)
doc.addResource(int(QTextDocument.ResourceType.ImageResource), QUrl('card://thumb'), c)
doc.setHtml(html)
self.doc = doc
@@ -224,8 +263,10 @@ class VirtualCardContainer(QWidget):
authors = db._all_field_for('authors', all_books, [_('Unknown author')])
series = db._all_field_for('series', all_books, '')
series_indices = db._all_field_for('series_index', all_books, 1)
+ abids = db._all_book_ids(lambda x: x)
+ in_db = {bid: bid in abids for bid in all_books}
for card in self._cards:
- card.results.preload(titles, authors, series, series_indices)
+ card.results.preload(titles, authors, series, series_indices, in_db)
def matches_found(self, num):
self._cards = tuple(CardData(r) for r in self.model.results) if num > 0 else ()
@@ -459,3 +500,6 @@ class CardsView(QWidget):
def shutdown(self):
self.view.shutdown()
+
+ def current_result(self):
+ return None, None
diff --git a/src/calibre/gui2/fts/search.py b/src/calibre/gui2/fts/search.py
index 1cdb67f2c2..587b2b905c 100644
--- a/src/calibre/gui2/fts/search.py
+++ b/src/calibre/gui2/fts/search.py
@@ -47,7 +47,7 @@ from calibre.db import FTSQueryError
from calibre.ebooks.metadata import authors_to_string, fmt_sidx
from calibre.gui2 import config, error_dialog, gprefs, info_dialog, question_dialog, safe_open_url
from calibre.gui2.fts.cards import CardsView
-from calibre.gui2.fts.utils import get_db, markup_text
+from calibre.gui2.fts.utils import get_db, jump_shortcut, markup_text
from calibre.gui2.library.models import render_pin
from calibre.gui2.ui import get_gui
from calibre.gui2.viewer.widgets import ResultsDelegate, SearchBox
@@ -58,7 +58,6 @@ from calibre.utils.localization import ngettext
ROOT = QModelIndex()
sanitize_text_pat = re.compile(r'\s+')
fts_url = 'https://www.sqlite.org/fts5.html#full_text_query_syntax'
-jump_shortcut = ''
def mark_books(*book_ids):
@@ -128,7 +127,7 @@ class SearchDelegate(ResultsDelegate):
class Results:
- _title = _authors = _series = _series_index = None
+ _title = _authors = _series = _series_index = _book_in_db = None
def __init__(self, book_id):
self.book_id = book_id
@@ -206,11 +205,18 @@ class Results:
self._series_index = 1
return self._series_index
- def preload(self, titles, authors, series, series_indices):
+ @property
+ def book_in_db(self):
+ if self._book_in_db is None:
+ self._book_in_db = get_db().has_book(self.book_id)
+ return self._book_in_db
+
+ def preload(self, titles, authors, series, series_indices, in_db):
self._title = titles[self.book_id]
self._authors = authors[self.book_id]
self._series = series[self.book_id]
self._series_index = series_indices[self.book_id]
+ self._book_in_db = in_db[self.book_id]
class ResultsModel(QAbstractItemModel):
@@ -713,11 +719,11 @@ class ResultDetails(QWidget):
ict = ''
text += '
{2}\xa0{0}\xa0\xa0\xa0 '.format( _('Select'), '
' + _('Scroll to this book in the calibre library book list and select it [{}]').format( - jump_shortcut), ict.format('lt.png')) + jump_shortcut()), ict.format('lt.png')) text += '{2}\xa0{0}
'.format( _('Mark'), '' + _( - 'Put a pin on this book in the calibre library, for future reference.' - ' You can search for marked books using the search term: {0}').format('
marked:true'), ict.format('marked.png')) + 'Put a pin on this book in the calibre library, for future reference.\n' + 'You can search for marked books using the search term: {0}').format('
marked:true'), ict.format('marked.png')) if get_db().has_id(results.book_id): text += '
{2}\xa0{0}'.format( _('Re-index'), _('Re-index this book. Useful if the book has been changed outside of calibre, and thus not automatically re-indexed.'), @@ -883,12 +889,11 @@ class ResultsPanel(QWidget): switch_to_scan_panel = pyqtSignal() def __init__(self, parent=None): - global jump_shortcut super().__init__(parent) self.jump_to_current_book_action = ac = QAction(self) ac.triggered.connect(self.jump_to_current_book) ac.setShortcut(QKeySequence('Ctrl+S', QKeySequence.SequenceFormat.PortableText)) - jump_shortcut = ac.shortcut().toString(QKeySequence.SequenceFormat.NativeText) + jump_shortcut(ac.shortcut().toString(QKeySequence.SequenceFormat.NativeText)) if isinstance(parent, QDialog): parent.finished.connect(self.shutdown) self.results_model = m = ResultsModel(self) diff --git a/src/calibre/gui2/fts/utils.py b/src/calibre/gui2/fts/utils.py index 77926511e7..9f2c1fd836 100644 --- a/src/calibre/gui2/fts/utils.py +++ b/src/calibre/gui2/fts/utils.py @@ -23,3 +23,9 @@ def markup_text(text: str) -> str: return '' if closing else '' return re.sub(r'\x1d', sub, prepare_string_for_xml(text)) + + +def jump_shortcut(new_val: str = '') -> str: + if new_val: + setattr(jump_shortcut, 'ans', new_val) + return getattr(jump_shortcut, 'ans', '')