mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Full text search window: Add actions to the context menu to open the book at the clicked on result. Also allow using the view book shortcut to open the currently selected search result. Fixes #2052462 [[Enhancement] Press V to view book in the Full text search dialog](https://bugs.launchpad.net/calibre/+bug/2052462)
This commit is contained in:
parent
f179b8c9b9
commit
2132e31339
@ -4,13 +4,15 @@
|
||||
|
||||
import os
|
||||
from qt.core import (
|
||||
QDialogButtonBox, QHBoxLayout, QIcon, QLabel, QSize, QStackedWidget, QVBoxLayout, Qt
|
||||
QAction, QDialogButtonBox, QHBoxLayout, QIcon, QLabel, QSize, QStackedWidget, Qt,
|
||||
QVBoxLayout,
|
||||
)
|
||||
|
||||
from calibre.gui2 import warning_dialog
|
||||
from calibre.gui2 import error_dialog, warning_dialog
|
||||
from calibre.gui2.fts.scan import ScanStatus
|
||||
from calibre.gui2.fts.search import ResultsPanel
|
||||
from calibre.gui2.fts.utils import get_db
|
||||
from calibre.gui2.ui import get_gui
|
||||
from calibre.gui2.widgets2 import Dialog
|
||||
|
||||
|
||||
@ -21,6 +23,16 @@ class FTSDialog(Dialog):
|
||||
default_buttons=QDialogButtonBox.StandardButton.Close)
|
||||
self.setWindowIcon(QIcon.ic('fts.png'))
|
||||
self.setWindowFlags(self.windowFlags() | Qt.WindowType.WindowMinMaxButtonsHint)
|
||||
self.view_action = ac = QAction(self)
|
||||
ac.triggered.connect(self.view_current_book)
|
||||
gui = get_gui()
|
||||
if gui is not None:
|
||||
ac.setShortcuts(gui.iactions['View'].menuless_qaction.shortcuts())
|
||||
self.addAction(ac)
|
||||
|
||||
def view_current_book(self):
|
||||
if not self.results_panel.view_current_result():
|
||||
error_dialog(self, _('No result selected'), _('Cannot view book as no result is selected'), show=True)
|
||||
|
||||
def setup_ui(self):
|
||||
l = QVBoxLayout(self)
|
||||
|
@ -57,6 +57,31 @@ def jump_to_book(book_id, parent=None):
|
||||
' only search currently visible books.'), show=True)
|
||||
|
||||
|
||||
def show_in_viewer(book_id, text, fmt):
|
||||
text = text.strip('…').replace('\x1d', '').replace('\xa0', ' ')
|
||||
text = sanitize_text_pat.sub(' ', text)
|
||||
gui = get_gui()
|
||||
if gui is not None:
|
||||
if fmt in config['internally_viewed_formats']:
|
||||
gui.iactions['View'].view_format_by_id(book_id, fmt, open_at=f'search:{text}')
|
||||
else:
|
||||
gui.iactions['View'].view_format_by_id(book_id, fmt)
|
||||
|
||||
|
||||
def open_book(results, match_index=None):
|
||||
gui = get_gui()
|
||||
if gui is None:
|
||||
return
|
||||
book_id = results.book_id
|
||||
if match_index is None:
|
||||
gui.iactions['View'].view_historical(book_id)
|
||||
return
|
||||
result_dict = results.result_dicts[match_index]
|
||||
formats = results.formats[match_index]
|
||||
from calibre.gui2.actions.view import preferred_format
|
||||
show_in_viewer(book_id, result_dict['text'], preferred_format(formats))
|
||||
|
||||
|
||||
class SearchDelegate(ResultsDelegate):
|
||||
|
||||
def result_data(self, result):
|
||||
@ -429,11 +454,27 @@ class ResultsView(QTreeView):
|
||||
if results:
|
||||
m.addAction(QIcon.ic('lt.png'), _('Jump to this book in the library'), partial(jump_to_book, results.book_id, self))
|
||||
m.addAction(QIcon.ic('marked.png'), _('Mark this book in the library'), partial(mark_books, results.book_id))
|
||||
if match is not None:
|
||||
match = index.row()
|
||||
m.addAction(QIcon.ic('view.png'), _('Open this book at this search result'), partial(open_book, results, match_index=match))
|
||||
else:
|
||||
m.addAction(QIcon.ic('view.png'), _('Open this book'), partial(open_book, results))
|
||||
m.addSeparator()
|
||||
m.addAction(QIcon.ic('plus.png'), _('Expand all'), self.expandAll)
|
||||
m.addAction(QIcon.ic('minus.png'), _('Collapse all'), self.collapseAll)
|
||||
m.exec(self.mapToGlobal(pos))
|
||||
|
||||
def view_current_result(self):
|
||||
idx = self.currentIndex()
|
||||
if idx.isValid():
|
||||
results, match = self.m.data_for_index(idx)
|
||||
if results:
|
||||
if match is not None:
|
||||
match = idx.row()
|
||||
open_book(results, match)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class Spinner(ProgressIndicator):
|
||||
|
||||
@ -813,6 +854,9 @@ class ResultsPanel(QWidget):
|
||||
if st is not None:
|
||||
s.restoreState(st)
|
||||
|
||||
def view_current_result(self):
|
||||
return self.results_view.view_current_result()
|
||||
|
||||
def clear_history(self):
|
||||
self.sip.clear_history()
|
||||
|
||||
@ -824,14 +868,7 @@ class ResultsPanel(QWidget):
|
||||
|
||||
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:
|
||||
if fmt in config['internally_viewed_formats']:
|
||||
gui.iactions['View'].view_format_by_id(book_id, fmt, open_at=f'search:{text}')
|
||||
else:
|
||||
gui.iactions['View'].view_format_by_id(book_id, fmt)
|
||||
show_in_viewer(book_id, r['text'], fmt)
|
||||
|
||||
def request_stop_search(self):
|
||||
if question_dialog(self, _('Are you sure?'), _('Abort the current search?')):
|
||||
|
Loading…
x
Reference in New Issue
Block a user