Viewer: Allow using search expressions for --open-at

This commit is contained in:
Kovid Goyal 2022-06-19 11:35:24 +05:30
parent 2843ec81e1
commit 30fe553c28
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 36 additions and 9 deletions

View File

@ -131,7 +131,10 @@ View an e-book.
'the string "something". The form toc-href:something will match the '
'href (internal link destination) of toc nodes. The matching is exact. '
'If you want to match a substring, use the form toc-href-contains:something. '
'The form ref:something will use Reference mode references.'))
'The form ref:something will use Reference mode references. The form search:something will'
' search for something after opening the book. The form regex:something will search'
' for the regular expression something after opening the book.'
))
a('--continue', default=False, action='store_true', dest='continue_reading',
help=_('Continue reading the last opened book'))
@ -197,7 +200,7 @@ def main(args=sys.argv):
oat = opts.open_at
if oat and not (
oat.startswith('toc:') or oat.startswith('toc-href:') or oat.startswith('toc-href-contains:') or
oat.startswith('epubcfi(/') or is_float(oat) or oat.startswith('ref:')):
oat.startswith('epubcfi(/') or is_float(oat) or oat.startswith('ref:') or oat.startswith('search:') or oat.startswith('regex:')):
raise SystemExit(f'Not a valid --open-at value: {opts.open_at}')
if get_session_pref('singleinstance', False):

View File

@ -319,9 +319,10 @@ def search_in_name(name, search_query, ctx_size=75):
yield match.span()
else:
spans = []
a = lambda s, l: spans.append((s, s + l))
primary_collator_without_punctuation().find_all(search_query.text, raw, a, search_query.mode == 'word')
miter = lambda: spans
if raw:
a = lambda s, l: spans.append((s, s + l))
primary_collator_without_punctuation().find_all(search_query.text, raw, a, search_query.mode == 'word')
for (start, end) in miter():
before = raw[max(0, start-ctx_size):start]
@ -454,9 +455,16 @@ class SearchInput(QWidget): # {{{
def find_previous(self):
self.emit_search(backwards=True)
def focus_input(self, text=None):
def focus_input(self, text=None, search_type=None, case_sensitive=None):
if text and hasattr(text, 'rstrip'):
self.search_box.setText(text)
if search_type is not None:
idx = self.query_type.findData(search_type)
if idx < 0:
idx = self.query_type.findData('normal')
self.query_type.setCurrentIndex(idx)
if case_sensitive is not None:
self.case_sensitive.setChecked(bool(case_sensitive))
self.search_box.setFocus(Qt.FocusReason.OtherFocusReason)
le = self.search_box.lineEdit()
le.end(False)
@ -668,8 +676,8 @@ class SearchPanel(QWidget): # {{{
def update_hidden_message(self):
self.hidden_message.setVisible(self.results.current_result_is_hidden)
def focus_input(self, text=None):
self.search_input.focus_input(text)
def focus_input(self, text=None, search_type=None, case_sensitive=None):
self.search_input.focus_input(text, search_type, case_sensitive)
def search_cleared(self):
self.results.clear_all_results()

View File

@ -99,6 +99,7 @@ class EbookViewer(MainWindow):
t.setSingleShot(True), t.setInterval(3000), t.setTimerType(Qt.TimerType.VeryCoarseTimer)
connect_lambda(t.timeout, self, lambda self: self.save_annotations(in_book_file=False))
self.pending_open_at = open_at
self.pending_search = None
self.base_window_title = _('E-book viewer')
self.setDockOptions(QMainWindow.DockOption.AnimatedDocks | QMainWindow.DockOption.AllowTabbedDocks | QMainWindow.DockOption.AllowNestedDocks)
self.setWindowTitle(self.base_window_title)
@ -195,6 +196,7 @@ class EbookViewer(MainWindow):
self.web_view.highlights_changed.connect(self.highlights_changed)
self.web_view.update_reading_rates.connect(self.update_reading_rates)
self.web_view.edit_book.connect(self.edit_book)
self.web_view.content_file_changed.connect(self.content_file_changed)
self.actions_toolbar.initialize(self.web_view, self.search_dock.toggleViewAction())
at.update_action_state(False)
self.setCentralWidget(self.web_view)
@ -310,11 +312,11 @@ class EbookViewer(MainWindow):
if not is_visible:
self.toc.scroll_to_current_toc_node()
def show_search(self, text, trigger=False):
def show_search(self, text, trigger=False, search_type=None, case_sensitive=None):
self.search_dock.setVisible(True)
self.search_dock.activateWindow()
self.search_dock.raise_()
self.search_widget.focus_input(text)
self.search_widget.focus_input(text, search_type, case_sensitive)
if trigger:
self.search_widget.trigger()
@ -425,6 +427,11 @@ class EbookViewer(MainWindow):
self.loading_overlay.hide()
self.actions_toolbar.update_action_state(True)
def content_file_changed(self, fname):
if self.pending_search:
search, self.pending_search = self.pending_search, None
self.show_search(text=search['query'], trigger=True, search_type=search['type'], case_sensitive=search['case_sensitive'])
def show_error(self, title, msg, details):
self.loading_overlay.hide()
error_dialog(self, title, msg, det_msg=details or None, show=True)
@ -526,6 +533,7 @@ class EbookViewer(MainWindow):
if self.shutting_down:
return
open_at, self.pending_open_at = self.pending_open_at, None
self.pending_search = None
self.web_view.clear_caches()
if not ok:
self.actions_toolbar.update_action_state(False)
@ -577,6 +585,12 @@ class EbookViewer(MainWindow):
initial_position = {'type': 'cfi', 'data': open_at}
elif open_at.startswith('ref:'):
initial_position = {'type': 'ref', 'data': open_at[len('ref:'):]}
elif open_at.startswith('search:'):
self.pending_search = {'type': 'normal', 'query': open_at[len('search:'):], 'case_sensitive': False}
initial_position = {'type': 'bookpos', 'data': 0}
elif open_at.startswith('regex:'):
self.pending_search = {'type': 'regex', 'query': open_at[len('regex:'):], 'case_sensitive': True}
initial_position = {'type': 'bookpos', 'data': 0}
elif is_float(open_at):
initial_position = {'type': 'bookpos', 'data': float(open_at)}
highlights = self.current_book_data['annotations_map']['highlight']

View File

@ -462,6 +462,7 @@ class WebView(RestartingWebEngineView):
paged_mode_changed = pyqtSignal()
standalone_misc_settings_changed = pyqtSignal(object)
view_created = pyqtSignal(object)
content_file_changed = pyqtSignal(str)
def __init__(self, parent=None):
self._host_widget = None
@ -623,6 +624,7 @@ class WebView(RestartingWebEngineView):
def on_content_file_changed(self, data):
self.current_content_file = data
self.content_file_changed.emit(self.current_content_file)
def start_book_load(self, initial_position=None, highlights=None, current_book_data=None, reading_rates=None):
key = (set_book_path.path,)