mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Open viewer at search result from FTS
This commit is contained in:
parent
97d613016c
commit
1956dc9967
@ -72,7 +72,7 @@ class Results:
|
|||||||
def __init__(self, book_id):
|
def __init__(self, book_id):
|
||||||
self.book_id = book_id
|
self.book_id = book_id
|
||||||
self.text_map = {}
|
self.text_map = {}
|
||||||
self.texts = []
|
self.result_dicts = []
|
||||||
self.formats = []
|
self.formats = []
|
||||||
|
|
||||||
def add_result_with_text(self, result):
|
def add_result_with_text(self, result):
|
||||||
@ -81,16 +81,16 @@ class Results:
|
|||||||
fmt = result['format']
|
fmt = result['format']
|
||||||
i = self.text_map.get(q)
|
i = self.text_map.get(q)
|
||||||
if i is None:
|
if i is None:
|
||||||
i = self.text_map[q] = len(self.texts)
|
i = self.text_map[q] = len(self.result_dicts)
|
||||||
self.texts.append(result)
|
self.result_dicts.append(result)
|
||||||
self.formats.append(set())
|
self.formats.append(set())
|
||||||
self.formats[i].add(fmt)
|
self.formats[i].add(fmt)
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.texts)
|
return len(self.result_dicts)
|
||||||
|
|
||||||
def __getitem__(self, x):
|
def __getitem__(self, x):
|
||||||
return self.texts[x]
|
return self.result_dicts[x]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def title(self):
|
def title(self):
|
||||||
@ -183,6 +183,11 @@ class ResultsModel(QAbstractItemModel):
|
|||||||
self.signal_search_complete(self.current_query_id)
|
self.signal_search_complete(self.current_query_id)
|
||||||
self.current_search_key = None # so that re-doing the search works
|
self.current_search_key = None # so that re-doing the search works
|
||||||
|
|
||||||
|
def get_result(self, book_id, result_num):
|
||||||
|
idx = self.result_map[book_id]
|
||||||
|
results = self.results[idx]
|
||||||
|
return results.result_dicts[result_num]
|
||||||
|
|
||||||
def search(self, fts_engine_query, use_stemming=True, restrict_to_book_ids=None):
|
def search(self, fts_engine_query, use_stemming=True, restrict_to_book_ids=None):
|
||||||
db = get_db()
|
db = get_db()
|
||||||
failure = []
|
failure = []
|
||||||
@ -501,6 +506,8 @@ class SearchInputPanel(QWidget):
|
|||||||
|
|
||||||
class ResultDetails(QWidget):
|
class ResultDetails(QWidget):
|
||||||
|
|
||||||
|
show_in_viewer = pyqtSignal(int, int, str)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.key = None
|
self.key = None
|
||||||
@ -529,8 +536,10 @@ class ResultDetails(QWidget):
|
|||||||
jump_to_book(self.current_book_id)
|
jump_to_book(self.current_book_id)
|
||||||
|
|
||||||
def results_anchor_clicked(self, url):
|
def results_anchor_clicked(self, url):
|
||||||
if self.current_book_id > 0:
|
if self.current_book_id > 0 and url.scheme() == 'book':
|
||||||
print(url)
|
book_id, result_num, fmt = url.path().strip('/').split('/')
|
||||||
|
book_id, result_num = int(book_id), int(result_num)
|
||||||
|
self.show_in_viewer.emit(int(book_id), int(result_num), fmt)
|
||||||
|
|
||||||
def resizeEvent(self, ev):
|
def resizeEvent(self, ev):
|
||||||
self.do_layout()
|
self.do_layout()
|
||||||
@ -554,7 +563,7 @@ class ResultDetails(QWidget):
|
|||||||
self.results.setGeometry(QRect(0, top, g.width(), g.height() - top))
|
self.results.setGeometry(QRect(0, top, g.width(), g.height() - top))
|
||||||
|
|
||||||
def show_result(self, results, individual_match=None):
|
def show_result(self, results, individual_match=None):
|
||||||
key = results.book_id, len(results.texts), individual_match
|
key = results.book_id, len(results.result_dicts), individual_match
|
||||||
if key == self.key:
|
if key == self.key:
|
||||||
return False
|
return False
|
||||||
old_current_book_id = self.current_book_id
|
old_current_book_id = self.current_book_id
|
||||||
@ -609,7 +618,7 @@ class ResultDetails(QWidget):
|
|||||||
return re.sub('\x1d', sub, re.sub(r'\s+', ' ', text))
|
return re.sub('\x1d', sub, re.sub(r'\s+', ' ', text))
|
||||||
|
|
||||||
ci = self.current_individual_match
|
ci = self.current_individual_match
|
||||||
for i, (result, formats) in enumerate(zip(results.texts, results.formats)):
|
for i, (result, formats) in enumerate(zip(results.result_dicts, results.formats)):
|
||||||
if ci is not None and ci != i:
|
if ci is not None and ci != i:
|
||||||
continue
|
continue
|
||||||
text = result['text']
|
text = result['text']
|
||||||
@ -619,7 +628,7 @@ class ResultDetails(QWidget):
|
|||||||
fmt = fmt.upper()
|
fmt = fmt.upper()
|
||||||
tt = _('Open the book, in the {fmt} format.\nWhen using the calibre viewer, it will attempt to scroll\nto this search result automatically.'
|
tt = _('Open the book, in the {fmt} format.\nWhen using the calibre viewer, it will attempt to scroll\nto this search result automatically.'
|
||||||
).format(fmt=fmt)
|
).format(fmt=fmt)
|
||||||
html.append(f'<a title="{tt}" href="book:///{self.current_book_id}/{fmt}">{fmt}</a>\xa0 ')
|
html.append(f'<a title="{tt}" href="book:///{self.current_book_id}/{i}/{fmt}">{fmt}</a>\xa0 ')
|
||||||
html.append(f'<p>{text}</p>')
|
html.append(f'<p>{text}</p>')
|
||||||
self.results.setHtml('\n'.join(html))
|
self.results.setHtml('\n'.join(html))
|
||||||
|
|
||||||
@ -632,6 +641,8 @@ class ResultDetails(QWidget):
|
|||||||
|
|
||||||
class DetailsPanel(QStackedWidget):
|
class DetailsPanel(QStackedWidget):
|
||||||
|
|
||||||
|
show_in_viewer = pyqtSignal(int, int, str)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
@ -670,6 +681,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)
|
||||||
self.addWidget(rd)
|
self.addWidget(rd)
|
||||||
|
|
||||||
def sizeHint(self):
|
def sizeHint(self):
|
||||||
@ -731,6 +743,7 @@ class ResultsPanel(QWidget):
|
|||||||
sip.clear_search.connect(self.clear_results)
|
sip.clear_search.connect(self.clear_results)
|
||||||
|
|
||||||
self.details = d = DetailsPanel(self)
|
self.details = d = DetailsPanel(self)
|
||||||
|
d.show_in_viewer.connect(self.show_in_viewer)
|
||||||
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)
|
||||||
@ -739,6 +752,14 @@ class ResultsPanel(QWidget):
|
|||||||
if st is not None:
|
if st is not None:
|
||||||
s.restoreState(st)
|
s.restoreState(st)
|
||||||
|
|
||||||
|
def show_in_viewer(self, book_id, result_num, fmt):
|
||||||
|
r = self.results_view.m.get_result(book_id, result_num)
|
||||||
|
text = r['text'].strip('…').replace('\x1d', '').replace('\xa0', ' ')
|
||||||
|
text = sanitize_text_pat.sub(' ', text)
|
||||||
|
gui = get_gui()
|
||||||
|
if gui is not None:
|
||||||
|
gui.iactions['View'].view_format_by_id(book_id, fmt, open_at=f'search:{text}')
|
||||||
|
|
||||||
def request_stop_search(self):
|
def request_stop_search(self):
|
||||||
if question_dialog(self, _('Are you sure?'), _('Abort the current search?')):
|
if question_dialog(self, _('Are you sure?'), _('Abort the current search?')):
|
||||||
self.results_view.m.abort_search()
|
self.results_view.m.abort_search()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user