Re-implement searching for QtWebKit
This commit is contained in:
parent
515d16f137
commit
0b88c5d413
@ -1400,17 +1400,6 @@ class CommandDispatcher:
|
||||
this.dispatchEvent(event);
|
||||
""".format(webelem.javascript_escape(sel)))
|
||||
|
||||
def _clear_search(self, view, text):
|
||||
"""Clear search string/highlights for the given view.
|
||||
|
||||
This does nothing if the view's search text is the same as the given
|
||||
text.
|
||||
"""
|
||||
if view.search_text is not None and view.search_text != text:
|
||||
# We first clear the marked text, then the highlights
|
||||
view.search('', 0)
|
||||
view.search('', QWebPage.HighlightAllOccurrences)
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', scope='window',
|
||||
maxsplit=0)
|
||||
def search(self, text="", reverse=False):
|
||||
@ -1421,27 +1410,18 @@ class CommandDispatcher:
|
||||
reverse: Reverse search direction.
|
||||
"""
|
||||
self.set_mark("'")
|
||||
view = self._current_widget()
|
||||
self._clear_search(view, text)
|
||||
flags = 0
|
||||
ignore_case = config.get('general', 'ignore-case')
|
||||
if ignore_case == 'smart':
|
||||
if not text.islower():
|
||||
flags |= QWebPage.FindCaseSensitively
|
||||
elif not ignore_case:
|
||||
flags |= QWebPage.FindCaseSensitively
|
||||
if config.get('general', 'wrap-search'):
|
||||
flags |= QWebPage.FindWrapsAroundDocument
|
||||
if reverse:
|
||||
flags |= QWebPage.FindBackward
|
||||
# We actually search *twice* - once to highlight everything, then again
|
||||
# to get a mark so we can navigate.
|
||||
view.search(text, flags)
|
||||
view.search(text, flags | QWebPage.HighlightAllOccurrences)
|
||||
view.search_text = text
|
||||
view.search_flags = flags
|
||||
tab = self._current_widget()
|
||||
tab.search.clear()
|
||||
|
||||
options = {
|
||||
'ignore_case': config.get('general', 'ignore-case'),
|
||||
'wrap': config.get('general', 'wrap-search'),
|
||||
'reverse': reverse,
|
||||
}
|
||||
tab.search.search(text, **options)
|
||||
|
||||
self._tabbed_browser.search_text = text
|
||||
self._tabbed_browser.search_flags = flags
|
||||
self._tabbed_browser.search_options = options
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', hide=True,
|
||||
scope='window')
|
||||
@ -1452,18 +1432,19 @@ class CommandDispatcher:
|
||||
Args:
|
||||
count: How many elements to ignore.
|
||||
"""
|
||||
tab = self._current_widget()
|
||||
window_text = self._tabbed_browser.search_text
|
||||
window_options = self._tabbed_browser.search_options
|
||||
|
||||
self.set_mark("'")
|
||||
view = self._current_widget()
|
||||
|
||||
self._clear_search(view, self._tabbed_browser.search_text)
|
||||
if window_text is not None and window_text != tab.search.text:
|
||||
tab.search.clear()
|
||||
tab.search.search(window_text, **window_options)
|
||||
count -= 1
|
||||
|
||||
if self._tabbed_browser.search_text is not None:
|
||||
view.search_text = self._tabbed_browser.search_text
|
||||
view.search_flags = self._tabbed_browser.search_flags
|
||||
view.search(view.search_text,
|
||||
view.search_flags | QWebPage.HighlightAllOccurrences)
|
||||
for _ in range(count):
|
||||
view.search(view.search_text, view.search_flags)
|
||||
for _ in range(count):
|
||||
tab.search.next_result()
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', hide=True,
|
||||
scope='window')
|
||||
@ -1474,25 +1455,19 @@ class CommandDispatcher:
|
||||
Args:
|
||||
count: How many elements to ignore.
|
||||
"""
|
||||
self.set_mark("'")
|
||||
view = self._current_widget()
|
||||
self._clear_search(view, self._tabbed_browser.search_text)
|
||||
tab = self._current_widget()
|
||||
window_text = self._tabbed_browser.search_text
|
||||
window_options = self._tabbed_browser.search_options
|
||||
|
||||
self.set_mark("'")
|
||||
|
||||
if window_text is not None and window_text != tab.search.text:
|
||||
tab.search.clear()
|
||||
tab.search.search(window_text, **window_options)
|
||||
count -= 1
|
||||
|
||||
if self._tabbed_browser.search_text is not None:
|
||||
view.search_text = self._tabbed_browser.search_text
|
||||
view.search_flags = self._tabbed_browser.search_flags
|
||||
view.search(view.search_text,
|
||||
view.search_flags | QWebPage.HighlightAllOccurrences)
|
||||
# The int() here serves as a QFlags constructor to create a copy of the
|
||||
# QFlags instance rather as a reference. I don't know why it works this
|
||||
# way, but it does.
|
||||
flags = int(view.search_flags)
|
||||
if flags & QWebPage.FindBackward:
|
||||
flags &= ~QWebPage.FindBackward
|
||||
else:
|
||||
flags |= QWebPage.FindBackward
|
||||
for _ in range(count):
|
||||
view.search(view.search_text, flags)
|
||||
tab.search.prev_result()
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', hide=True,
|
||||
modes=[KeyMode.caret], scope='window')
|
||||
|
@ -56,6 +56,46 @@ class WrapperLayout(QLayout):
|
||||
self._widget.setGeometry(r)
|
||||
|
||||
|
||||
class AbstractSearch(QObject):
|
||||
|
||||
"""Attribute of AbstractTab for doing searches.
|
||||
|
||||
Attributes:
|
||||
widget: The underlying WebView widget.
|
||||
text: The last thing this view was searched for.
|
||||
_flags: The flags of the last search.
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.widget = None
|
||||
self.text = None
|
||||
self._flags = 0
|
||||
|
||||
def search(self, text, *, ignore_case=False, wrap=False):
|
||||
"""Find the given text on the page.
|
||||
|
||||
Args:
|
||||
text: The text to search for.
|
||||
ignore_case: Search case-insensitively. (True/False/'smart')
|
||||
wrap: Wrap around to the top when arriving at the bottom.
|
||||
reverse: Reverse search direction.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def clear(self):
|
||||
"""Clear the current search."""
|
||||
raise NotImplementedError
|
||||
|
||||
def prev_result(self):
|
||||
"""Go to the previous result of the current search."""
|
||||
raise NotImplementedError
|
||||
|
||||
def next_result(self):
|
||||
"""Go to the next result of the current search."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class AbstractZoom(QObject):
|
||||
|
||||
"""Attribute of AbstractTab for controlling zoom.
|
||||
@ -357,6 +397,7 @@ class AbstractTab(QWidget):
|
||||
# self.scroll = AbstractScroller(parent=self)
|
||||
# self.caret = AbstractCaret(win_id=win_id, parent=self)
|
||||
# self.zoom = AbstractZoom(win_id=win_id)
|
||||
# self.search = AbstractSearch(parent=self)
|
||||
self._layout = None
|
||||
self._widget = None
|
||||
self.keep_icon = False # FIXME:refactor get rid of this?
|
||||
@ -368,6 +409,7 @@ class AbstractTab(QWidget):
|
||||
self.scroll.widget = widget
|
||||
self.caret.widget = widget
|
||||
self.zoom.widget = widget
|
||||
self.search.widget = widget
|
||||
widget.mouse_wheel_zoom.connect(self.zoom.on_mouse_wheel_zoom)
|
||||
widget.setParent(self)
|
||||
|
||||
|
@ -31,6 +31,13 @@ from qutebrowser.browser import tab
|
||||
from qutebrowser.utils import usertypes, qtutils
|
||||
|
||||
|
||||
class WebEngineSearch(tab.AbstractSearch):
|
||||
|
||||
## TODO
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class WebEngineCaret(tab.AbstractCaret):
|
||||
|
||||
## TODO
|
||||
@ -100,6 +107,7 @@ class WebEngineViewTab(tab.AbstractTab):
|
||||
self.scroll = WebEngineScroller()
|
||||
self.caret = WebEngineCaret(win_id=win_id, parent=self)
|
||||
self.zoom = WebEngineZoom(win_id=win_id, parent=self)
|
||||
self.search = WebEngineSearch(parent=self)
|
||||
self._set_widget(widget)
|
||||
self._connect_signals()
|
||||
|
||||
|
@ -31,6 +31,46 @@ from qutebrowser.browser.webkit import webview
|
||||
from qutebrowser.utils import qtutils, objreg, usertypes, utils
|
||||
|
||||
|
||||
class WebViewSearch(tab.AbstractSearch):
|
||||
|
||||
def clear(self):
|
||||
# We first clear the marked text, then the highlights
|
||||
self.widget.search('', 0)
|
||||
self.widget.search('', QWebPage.HighlightAllOccurrences)
|
||||
|
||||
def search(self, text, *, ignore_case=False, wrap=False, reverse=False):
|
||||
flags = 0
|
||||
if ignore_case == 'smart':
|
||||
if not text.islower():
|
||||
flags |= QWebPage.FindCaseSensitively
|
||||
elif not ignore_case:
|
||||
flags |= QWebPage.FindCaseSensitively
|
||||
if wrap:
|
||||
flags |= QWebPage.FindWrapsAroundDocument
|
||||
if reverse:
|
||||
flags |= QWebPage.FindBackward
|
||||
# We actually search *twice* - once to highlight everything, then again
|
||||
# to get a mark so we can navigate.
|
||||
self.widget.search(text, flags)
|
||||
self.widget.search(text, flags | QWebPage.HighlightAllOccurrences)
|
||||
self.text = text
|
||||
self._flags = flags
|
||||
|
||||
def next_result(self):
|
||||
self.widget.search(self.text, self._flags)
|
||||
|
||||
def prev_result(self):
|
||||
# The int() here serves as a QFlags constructor to create a copy of the
|
||||
# QFlags instance rather as a reference. I don't know why it works this
|
||||
# way, but it does.
|
||||
flags = int(self._flags)
|
||||
if flags & QWebPage.FindBackward:
|
||||
flags &= ~QWebPage.FindBackward
|
||||
else:
|
||||
flags |= QWebPage.FindBackward
|
||||
self.widget.search(self.text, flags)
|
||||
|
||||
|
||||
class WebViewCaret(tab.AbstractCaret):
|
||||
|
||||
@pyqtSlot(usertypes.KeyMode)
|
||||
@ -376,6 +416,7 @@ class WebViewTab(tab.AbstractTab):
|
||||
self.scroll = WebViewScroller(parent=self)
|
||||
self.caret = WebViewCaret(win_id=win_id, parent=self)
|
||||
self.zoom = WebViewZoom(win_id=win_id, parent=self)
|
||||
self.search = WebViewSearch(parent=self)
|
||||
self._set_widget(widget)
|
||||
self._connect_signals()
|
||||
self.zoom._set_default_zoom()
|
||||
|
@ -54,8 +54,6 @@ class WebView(QWebView):
|
||||
code.
|
||||
registry: The ObjectRegistry associated with this tab.
|
||||
win_id: The window ID of the view.
|
||||
search_text: The text of the last search.
|
||||
search_flags: The search flags of the last search.
|
||||
_tab_id: The tab ID of the view.
|
||||
_has_ssl_errors: Whether SSL errors occurred during loading.
|
||||
_old_scroll_pos: The old scroll position.
|
||||
@ -101,8 +99,6 @@ class WebView(QWebView):
|
||||
self._has_ssl_errors = False
|
||||
self._ignore_wheel_event = False
|
||||
self.keep_icon = False
|
||||
self.search_text = None
|
||||
self.search_flags = 0
|
||||
self._set_bg_color()
|
||||
self.cur_url = QUrl()
|
||||
self.progress = 0
|
||||
|
@ -57,8 +57,8 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
emitted if the signal occurred in the current tab.
|
||||
|
||||
Attributes:
|
||||
search_text/search_flags: Search parameters which are shared between
|
||||
all tabs.
|
||||
search_text/search_options: Search parameters which are shared between
|
||||
all tabs.
|
||||
_win_id: The window ID this tabbedbrowser is associated with.
|
||||
_filter: A SignalFilter instance.
|
||||
_now_focused: The tab which is focused now.
|
||||
@ -118,7 +118,7 @@ class TabbedBrowser(tabwidget.TabWidget):
|
||||
self._filter = signalfilter.SignalFilter(win_id, self)
|
||||
self._now_focused = None
|
||||
self.search_text = None
|
||||
self.search_flags = 0
|
||||
self.search_options = {}
|
||||
self._local_marks = {}
|
||||
self._global_marks = {}
|
||||
self.default_window_icon = self.window().windowIcon()
|
||||
|
Loading…
Reference in New Issue
Block a user