mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Allow removing individual books from the FTS index if they are somehow missing from the main db
This commit is contained in:
parent
04ac88cfa4
commit
4467f1e54c
@ -979,6 +979,9 @@ class DB:
|
|||||||
if self.fts is not None:
|
if self.fts is not None:
|
||||||
return self.fts.commit_result(book_id, fmt, fmt_size, fmt_hash, text, err_msg)
|
return self.fts.commit_result(book_id, fmt, fmt_size, fmt_hash, text, err_msg)
|
||||||
|
|
||||||
|
def fts_unindex(self, book_id, fmt=None):
|
||||||
|
self.fts.unindex(book_id, fmt=fmt)
|
||||||
|
|
||||||
def fts_search(self,
|
def fts_search(self,
|
||||||
fts_engine_query, use_stemming, highlight_start, highlight_end, snippet_size, restrict_to_book_ids, return_text,
|
fts_engine_query, use_stemming, highlight_start, highlight_end, snippet_size, restrict_to_book_ids, return_text,
|
||||||
):
|
):
|
||||||
|
@ -475,6 +475,10 @@ class Cache:
|
|||||||
self.fts_job_queue = Queue()
|
self.fts_job_queue = Queue()
|
||||||
return fts
|
return fts
|
||||||
|
|
||||||
|
@write_api
|
||||||
|
def fts_unindex(self, book_id, fmt=None):
|
||||||
|
self.backend.fts_unindex(book_id, fmt=fmt)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def dispatch_fts_jobs(queue, dbref):
|
def dispatch_fts_jobs(queue, dbref):
|
||||||
from .fts.text import is_fmt_ok
|
from .fts.text import is_fmt_ok
|
||||||
|
@ -87,6 +87,13 @@ class FTS:
|
|||||||
conn = self.get_connection()
|
conn = self.get_connection()
|
||||||
conn.execute('DELETE FROM fts_db.dirtied_formats WHERE book=? AND format=?', (book_id, fmt.upper()))
|
conn.execute('DELETE FROM fts_db.dirtied_formats WHERE book=? AND format=?', (book_id, fmt.upper()))
|
||||||
|
|
||||||
|
def unindex(self, book_id, fmt=None):
|
||||||
|
conn = self.get_connection()
|
||||||
|
if fmt is None:
|
||||||
|
conn.execute('DELETE FROM books_text WHERE book=?', (book_id,))
|
||||||
|
else:
|
||||||
|
conn.execute('DELETE FROM books_text WHERE book=? AND format=?', (book_id, fmt.upper()))
|
||||||
|
|
||||||
def add_text(self, book_id, fmt, text, text_hash='', fmt_size=0, fmt_hash='', err_msg=''):
|
def add_text(self, book_id, fmt, text, text_hash='', fmt_size=0, fmt_hash='', err_msg=''):
|
||||||
conn = self.get_connection()
|
conn = self.get_connection()
|
||||||
ts = (utcnow() - EPOCH).total_seconds()
|
ts = (utcnow() - EPOCH).total_seconds()
|
||||||
|
@ -237,6 +237,17 @@ class ResultsModel(QAbstractItemModel):
|
|||||||
self.current_thread.start()
|
self.current_thread.start()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def remove_book(self, book_id):
|
||||||
|
idx = self.result_map.get(book_id)
|
||||||
|
if idx is not None:
|
||||||
|
self.beginRemoveRows(ROOT, idx, idx)
|
||||||
|
del self.results[idx]
|
||||||
|
del self.result_map[book_id]
|
||||||
|
self.endRemoveRows()
|
||||||
|
self.matches_found.emit(len(self.results))
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def search_text_in_thread(self, query_id, abort, *a, **kw):
|
def search_text_in_thread(self, query_id, abort, *a, **kw):
|
||||||
db = get_db()
|
db = get_db()
|
||||||
generator = db.fts_search(*a, **kw, result_type=lambda x: x)
|
generator = db.fts_search(*a, **kw, result_type=lambda x: x)
|
||||||
@ -506,6 +517,7 @@ class SearchInputPanel(QWidget):
|
|||||||
class ResultDetails(QWidget):
|
class ResultDetails(QWidget):
|
||||||
|
|
||||||
show_in_viewer = pyqtSignal(int, int, str)
|
show_in_viewer = pyqtSignal(int, int, str)
|
||||||
|
remove_book_from_results = pyqtSignal(int)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@ -533,6 +545,10 @@ class ResultDetails(QWidget):
|
|||||||
mark_books(self.current_book_id)
|
mark_books(self.current_book_id)
|
||||||
elif url.host() == 'jump':
|
elif url.host() == 'jump':
|
||||||
jump_to_book(self.current_book_id)
|
jump_to_book(self.current_book_id)
|
||||||
|
elif url.host() == 'unindex':
|
||||||
|
db = get_db()
|
||||||
|
db.fts_unindex(self.current_book_id)
|
||||||
|
self.remove_book_from_results.emit(self.current_book_id)
|
||||||
|
|
||||||
def results_anchor_clicked(self, url):
|
def results_anchor_clicked(self, url):
|
||||||
if self.current_book_id > 0 and url.scheme() == 'book':
|
if self.current_book_id > 0 and url.scheme() == 'book':
|
||||||
@ -601,6 +617,10 @@ class ResultDetails(QWidget):
|
|||||||
_('Mark'), '<p>' + _(
|
_('Mark'), '<p>' + _(
|
||||||
'Put a pin on this book in the calibre library, for future reference.'
|
'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('<p>marked:true'))
|
' You can search for marked books using the search term: {0}').format('<p>marked:true'))
|
||||||
|
if not get_db().has_id(results.book_id):
|
||||||
|
text += '<p><a href="calibre://unindex" title="{1}"><img valign="bottom" src="calibre-icon:///trash.png" width=16 height=16>\xa0{0}</a>'.format(
|
||||||
|
_('Remove from index'), _('This book has been deleted from the library but is still present in the'
|
||||||
|
' full text search index. Remove it.'))
|
||||||
self.book_info.setHtml(text)
|
self.book_info.setHtml(text)
|
||||||
|
|
||||||
def render_results(self, results, individual_match=None):
|
def render_results(self, results, individual_match=None):
|
||||||
@ -643,6 +663,7 @@ class ResultDetails(QWidget):
|
|||||||
class DetailsPanel(QStackedWidget):
|
class DetailsPanel(QStackedWidget):
|
||||||
|
|
||||||
show_in_viewer = pyqtSignal(int, int, str)
|
show_in_viewer = pyqtSignal(int, int, str)
|
||||||
|
remove_book_from_results = pyqtSignal(int)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@ -683,6 +704,7 @@ p { margin: 0; }
|
|||||||
|
|
||||||
self.result_details = rd = ResultDetails(self)
|
self.result_details = rd = ResultDetails(self)
|
||||||
rd.show_in_viewer.connect(self.show_in_viewer)
|
rd.show_in_viewer.connect(self.show_in_viewer)
|
||||||
|
rd.remove_book_from_results.connect(self.remove_book_from_results)
|
||||||
self.addWidget(rd)
|
self.addWidget(rd)
|
||||||
|
|
||||||
def sizeHint(self):
|
def sizeHint(self):
|
||||||
@ -745,6 +767,7 @@ class ResultsPanel(QWidget):
|
|||||||
|
|
||||||
self.details = d = DetailsPanel(self)
|
self.details = d = DetailsPanel(self)
|
||||||
d.show_in_viewer.connect(self.show_in_viewer)
|
d.show_in_viewer.connect(self.show_in_viewer)
|
||||||
|
d.remove_book_from_results.connect(self.remove_book_from_results)
|
||||||
rv.current_changed.connect(d.show_result)
|
rv.current_changed.connect(d.show_result)
|
||||||
rv.search_started.connect(d.clear)
|
rv.search_started.connect(d.clear)
|
||||||
rv.result_with_context_found.connect(d.result_with_context_found)
|
rv.result_with_context_found.connect(d.result_with_context_found)
|
||||||
@ -753,6 +776,9 @@ class ResultsPanel(QWidget):
|
|||||||
if st is not None:
|
if st is not None:
|
||||||
s.restoreState(st)
|
s.restoreState(st)
|
||||||
|
|
||||||
|
def remove_book_from_results(self, book_id):
|
||||||
|
self.results_view.m.remove_book(book_id)
|
||||||
|
|
||||||
def show_in_viewer(self, book_id, result_num, fmt):
|
def show_in_viewer(self, book_id, result_num, fmt):
|
||||||
r = self.results_view.m.get_result(book_id, result_num)
|
r = self.results_view.m.get_result(book_id, result_num)
|
||||||
text = r['text'].strip('…').replace('\x1d', '').replace('\xa0', ' ')
|
text = r['text'].strip('…').replace('\x1d', '').replace('\xa0', ' ')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user