diff options
Diffstat (limited to 'qutebrowser/browser/webengine/webenginetab.py')
-rw-r--r-- | qutebrowser/browser/webengine/webenginetab.py | 135 |
1 files changed, 63 insertions, 72 deletions
diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 0a2333afc..1d02f7e99 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -104,83 +104,33 @@ class _WebEngineSearchWrapHandler: Attributes: flag_wrap: An additional flag indicating whether the last search used wrapping. - _active_match: The 1-based index of the currently active match - on the page. - _total_matches: The total number of search matches on the page. - _nowrap_available: Whether the functionality to prevent wrapping - is available. + nowrap_available: Whether the functionality to prevent wrapping + is available. """ def __init__(self): - self._active_match = 0 - self._total_matches = 0 self.flag_wrap = True - self._nowrap_available = False + self.nowrap_available = False - def connect_signal(self, page): - """Connect to the findTextFinished signal of the page. - - Args: - page: The QtWebEnginePage to connect to this handler. - """ - if not qtutils.version_check("5.14"): - return - - try: - # pylint: disable=unused-import - from PyQt5.QtWebEngineCore import QWebEngineFindTextResult - except ImportError: - # WORKAROUND for some odd PyQt/packaging bug where the - # findTextResult signal is available, but QWebEngineFindTextResult - # is not. Seems to happen on e.g. Gentoo. - log.webview.warning("Could not import QWebEngineFindTextResult " - "despite running on Qt 5.14. You might need " - "to rebuild PyQtWebEngine.") - return - - page.findTextFinished.connect(self._store_match_data) - self._nowrap_available = True - - def _store_match_data(self, result): - """Store information on the last match. - - The information will be checked against when wrapping is turned off. - - Args: - result: A FindTextResult passed by the findTextFinished signal. - """ - self._active_match = result.activeMatch() - self._total_matches = result.numberOfMatches() - log.webview.debug("Active search match: {}/{}" - .format(self._active_match, self._total_matches)) - - def reset_match_data(self): - """Reset match information. - - Stale information could lead to next_result or prev_result misbehaving. - """ - self._active_match = 0 - self._total_matches = 0 - - def prevent_wrapping(self, *, going_up): + def prevent_wrapping(self, current_match, total_match_count, *, going_up): """Prevent wrapping if possible and required. Returns True if a wrap was prevented and False if not. Args: + current_match: The currently active search match on the page. + total_match_count: The total number of search matches on the page. going_up: Whether the search would scroll the page up or down. """ - if (not self._nowrap_available or - self.flag_wrap or self._total_matches == 0): - return False - elif going_up and self._active_match == 1: - message.info("Search hit TOP") - return True - elif not going_up and self._active_match == self._total_matches: - message.info("Search hit BOTTOM") - return True - else: - return False + return ( + self.nowrap_available and + not self.flag_wrap and + total_match_count != 0 and + ( + going_up and current_match == 1 or + not going_up and current_match == total_match_count + ) + ) class WebEngineSearch(browsertab.AbstractSearch): @@ -191,6 +141,7 @@ class WebEngineSearch(browsertab.AbstractSearch): _flags: The QWebEnginePage.FindFlags of the last search. _pending_searches: How many searches have been started but not called back yet. + """ _widget: webview.WebEngineView @@ -199,7 +150,6 @@ class WebEngineSearch(browsertab.AbstractSearch): super().__init__(tab, parent) self._flags = self._empty_flags() self._pending_searches = 0 - # The API necessary to stop wrapping was added in this version self._wrap_handler = _WebEngineSearchWrapHandler() def _empty_flags(self): @@ -214,7 +164,25 @@ class WebEngineSearch(browsertab.AbstractSearch): return flags def connect_signals(self): - self._wrap_handler.connect_signal(self._widget.page()) + """Connect the signals necessary for this class to function.""" + # The API necessary to stop wrapping was added in this version + if not qtutils.version_check("5.14"): + return + + try: + # pylint: disable=unused-import + from PyQt5.QtWebEngineCore import QWebEngineFindTextResult + except ImportError: + # WORKAROUND for some odd PyQt/packaging bug where the + # findTextResult signal is available, but QWebEngineFindTextResult + # is not. Seems to happen on e.g. Gentoo. + log.webview.warning("Could not import QWebEngineFindTextResult " + "despite running on Qt 5.14. You might need " + "to rebuild PyQtWebEngine.") + return + + self._wrap_handler.nowrap_available = True + self._widget.page().findTextFinished.connect(self._on_find_finished) def _find(self, text, flags, callback, caller): """Call findText on the widget.""" @@ -254,6 +222,14 @@ class WebEngineSearch(browsertab.AbstractSearch): self._widget.page().findText(text, flags, wrapped_callback) + def _on_find_finished(self, find_text_result): + """Unwrap the result, store it, and pass it along.""" + self.current_match = find_text_result.activeMatch() + self.total_match_count = find_text_result.numberOfMatches() + log.webview.debug("Active search match: {}/{}" + .format(self.current_match, self.total_match_count)) + self.search_match_changed.emit(self.current_match, self.total_match_count) + def search(self, text, *, ignore_case=usertypes.IgnoreCase.never, reverse=False, wrap=True, result_cb=None): # Don't go to next entry on duplicate search @@ -265,7 +241,7 @@ class WebEngineSearch(browsertab.AbstractSearch): self.text = text self._flags = self._args_to_flags(reverse, ignore_case) - self._wrap_handler.reset_match_data() + self._reset_match_data() self._wrap_handler.flag_wrap = wrap self._find(text, self._flags, result_cb, 'search') @@ -273,29 +249,44 @@ class WebEngineSearch(browsertab.AbstractSearch): def clear(self): if self.search_displayed: self.cleared.emit() + self.search_match_changed.emit(0, 0) self.search_displayed = False - self._wrap_handler.reset_match_data() + self._reset_match_data() self._widget.page().findText('') def prev_result(self, *, result_cb=None): # The int() here makes sure we get a copy of the flags. flags = QWebEnginePage.FindFlags(int(self._flags)) if flags & QWebEnginePage.FindBackward: - if self._wrap_handler.prevent_wrapping(going_up=False): + if self._wrap_handler.prevent_wrapping(self.current_match, + self.total_match_count, going_up=False): + result_cb(True) return flags &= ~QWebEnginePage.FindBackward else: - if self._wrap_handler.prevent_wrapping(going_up=True): + if self._wrap_handler.prevent_wrapping(self.current_match, + self.total_match_count, going_up=True): + result_cb(True) return flags |= QWebEnginePage.FindBackward self._find(self.text, flags, result_cb, 'prev_result') def next_result(self, *, result_cb=None): going_up = self._flags & QWebEnginePage.FindBackward - if self._wrap_handler.prevent_wrapping(going_up=going_up): + if self._wrap_handler.prevent_wrapping(self.current_match, + self.total_match_count, going_up=going_up): + result_cb(True) return self._find(self.text, self._flags, result_cb, 'next_result') + def _reset_match_data(self): + """Reset match counter information. + + Stale information could lead to next_result or prev_result misbehaving. + """ + self.current_match = 0 + self.total_match_count = 0 + class WebEngineCaret(browsertab.AbstractCaret): |