Add type hints for qutebrowser.browser.browsertab
This commit is contained in:
parent
f36a98ec76
commit
d7786c694f
3
mypy.ini
3
mypy.ini
@ -49,3 +49,6 @@ ignore_missing_imports = True
|
||||
[mypy-qutebrowser.browser.webkit.rfc6266]
|
||||
# subclasses dynamic PyPEG2 classes
|
||||
disallow_subclassing_any = False
|
||||
|
||||
[mypy-qutebrowser.browser.browsertab]
|
||||
disallow_untyped_defs = True
|
||||
|
@ -21,12 +21,19 @@
|
||||
|
||||
import enum
|
||||
import itertools
|
||||
import typing
|
||||
|
||||
import attr
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject, QSizeF, Qt
|
||||
from PyQt5.QtCore import (pyqtSignal, pyqtSlot, QUrl, QObject, QSizeF, Qt,
|
||||
QEvent, QPoint)
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtWidgets import QWidget, QApplication, QDialog
|
||||
from PyQt5.QtPrintSupport import QPrintDialog
|
||||
from PyQt5.QtPrintSupport import QPrintDialog, QPrinter
|
||||
from PyQt5.QtNetwork import QNetworkAccessManager
|
||||
MYPY = False
|
||||
if MYPY:
|
||||
# pylint: disable=unused-import
|
||||
from PyQt5.QtWebEngineWidgets import QWebEngineView
|
||||
|
||||
import pygments
|
||||
import pygments.lexers
|
||||
@ -37,14 +44,19 @@ from qutebrowser.config import config
|
||||
from qutebrowser.utils import (utils, objreg, usertypes, log, qtutils,
|
||||
urlutils, message)
|
||||
from qutebrowser.misc import miscwidgets, objects
|
||||
from qutebrowser.browser import mouse, hints
|
||||
from qutebrowser.browser import mouse, hints, webelem
|
||||
from qutebrowser.qt import sip
|
||||
if MYPY:
|
||||
# pylint: disable=unused-import
|
||||
from qutebrowser.browser.inspector import AbstractWebInspector
|
||||
|
||||
|
||||
tab_id_gen = itertools.count(0)
|
||||
|
||||
|
||||
def create(win_id, private, parent=None):
|
||||
def create(win_id: int,
|
||||
private: bool,
|
||||
parent: QWidget = None) -> 'AbstractTab':
|
||||
"""Get a QtWebKit/QtWebEngine tab object.
|
||||
|
||||
Args:
|
||||
@ -65,7 +77,7 @@ def create(win_id, private, parent=None):
|
||||
parent=parent)
|
||||
|
||||
|
||||
def init():
|
||||
def init() -> None:
|
||||
"""Initialize backend-specific modules."""
|
||||
if objects.backend == usertypes.Backend.QtWebEngine:
|
||||
from qutebrowser.browser.webengine import webenginetab
|
||||
@ -112,17 +124,18 @@ class TabData:
|
||||
input_mode: current input mode for the tab.
|
||||
"""
|
||||
|
||||
keep_icon = attr.ib(False)
|
||||
viewing_source = attr.ib(False)
|
||||
inspector = attr.ib(None)
|
||||
open_target = attr.ib(usertypes.ClickTarget.normal)
|
||||
override_target = attr.ib(None)
|
||||
pinned = attr.ib(False)
|
||||
fullscreen = attr.ib(False)
|
||||
netrc_used = attr.ib(False)
|
||||
input_mode = attr.ib(usertypes.KeyMode.normal)
|
||||
keep_icon = attr.ib(False) # type: bool
|
||||
viewing_source = attr.ib(False) # type: bool
|
||||
inspector = attr.ib(None) # type: typing.Optional[AbstractWebInspector]
|
||||
open_target = attr.ib(
|
||||
usertypes.ClickTarget.normal) # type: usertypes.ClickTarget
|
||||
override_target = attr.ib(None) # type: usertypes.ClickTarget
|
||||
pinned = attr.ib(False) # type: bool
|
||||
fullscreen = attr.ib(False) # type: bool
|
||||
netrc_used = attr.ib(False) # type: bool
|
||||
input_mode = attr.ib(usertypes.KeyMode.normal) # type: usertypes.KeyMode
|
||||
|
||||
def should_show_icon(self):
|
||||
def should_show_icon(self) -> bool:
|
||||
return (config.val.tabs.favicons.show == 'always' or
|
||||
config.val.tabs.favicons.show == 'pinned' and self.pinned)
|
||||
|
||||
@ -139,33 +152,35 @@ class AbstractAction:
|
||||
action_class = None # type: type
|
||||
action_base = None # type: type
|
||||
|
||||
def __init__(self, tab):
|
||||
self._widget = None
|
||||
def __init__(self, tab: 'AbstractTab') -> None:
|
||||
self._widget = typing.cast('QWebEngineView', None)
|
||||
self._tab = tab
|
||||
|
||||
def exit_fullscreen(self):
|
||||
def exit_fullscreen(self) -> None:
|
||||
"""Exit the fullscreen mode."""
|
||||
raise NotImplementedError
|
||||
|
||||
def save_page(self):
|
||||
def save_page(self) -> None:
|
||||
"""Save the current page."""
|
||||
raise NotImplementedError
|
||||
|
||||
def run_string(self, name):
|
||||
def run_string(self, name: str) -> None:
|
||||
"""Run a webaction based on its name."""
|
||||
member = getattr(self.action_class, name, None)
|
||||
if not isinstance(member, self.action_base):
|
||||
raise WebTabError("{} is not a valid web action!".format(name))
|
||||
self._widget.triggerPageAction(member)
|
||||
self._widget.triggerPageAction(member) # type: ignore
|
||||
|
||||
def show_source(self,
|
||||
pygments=False): # pylint: disable=redefined-outer-name
|
||||
def show_source(
|
||||
self,
|
||||
pygments: bool = False # pylint: disable=redefined-outer-name
|
||||
) -> None:
|
||||
"""Show the source of the current page in a new tab."""
|
||||
raise NotImplementedError
|
||||
|
||||
def _show_source_pygments(self):
|
||||
def _show_source_pygments(self) -> None:
|
||||
|
||||
def show_source_cb(source):
|
||||
def show_source_cb(source: str) -> None:
|
||||
"""Show source as soon as it's ready."""
|
||||
# WORKAROUND for https://github.com/PyCQA/pylint/issues/491
|
||||
# pylint: disable=no-member
|
||||
@ -188,23 +203,24 @@ class AbstractPrinting:
|
||||
|
||||
"""Attribute of AbstractTab for printing the page."""
|
||||
|
||||
def __init__(self, tab):
|
||||
def __init__(self, tab: 'AbstractTab') -> None:
|
||||
self._widget = None
|
||||
self._tab = tab
|
||||
|
||||
def check_pdf_support(self):
|
||||
def check_pdf_support(self) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def check_printer_support(self):
|
||||
def check_printer_support(self) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def check_preview_support(self):
|
||||
def check_preview_support(self) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def to_pdf(self, filename):
|
||||
def to_pdf(self, filename: str) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def to_printer(self, printer, callback=None):
|
||||
def to_printer(self, printer: QPrinter,
|
||||
callback: typing.Callable[[bool], None] = None) -> None:
|
||||
"""Print the tab.
|
||||
|
||||
Args:
|
||||
@ -214,17 +230,17 @@ class AbstractPrinting:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def show_dialog(self):
|
||||
def show_dialog(self) -> None:
|
||||
"""Print with a QPrintDialog."""
|
||||
self.check_printer_support()
|
||||
|
||||
def print_callback(ok):
|
||||
def print_callback(ok: bool) -> None:
|
||||
"""Called when printing finished."""
|
||||
if not ok:
|
||||
message.error("Printing failed!")
|
||||
diag.deleteLater()
|
||||
|
||||
def do_print():
|
||||
def do_print() -> None:
|
||||
"""Called when the dialog was closed."""
|
||||
self.to_printer(diag.printer(), print_callback)
|
||||
|
||||
@ -257,15 +273,16 @@ class AbstractSearch(QObject):
|
||||
|
||||
finished = pyqtSignal(bool)
|
||||
cleared = pyqtSignal()
|
||||
_Callback = typing.Callable[[bool], None]
|
||||
|
||||
def __init__(self, tab, parent=None):
|
||||
def __init__(self, tab: 'AbstractTab', parent: QWidget = None):
|
||||
super().__init__(parent)
|
||||
self._tab = tab
|
||||
self._widget = None
|
||||
self.text = None
|
||||
self.text = None # type: typing.Optional[str]
|
||||
self.search_displayed = False
|
||||
|
||||
def _is_case_sensitive(self, ignore_case):
|
||||
def _is_case_sensitive(self, ignore_case: str) -> bool:
|
||||
"""Check if case-sensitivity should be used.
|
||||
|
||||
This assumes self.text is already set properly.
|
||||
@ -273,6 +290,7 @@ class AbstractSearch(QObject):
|
||||
Arguments:
|
||||
ignore_case: The ignore_case value from the config.
|
||||
"""
|
||||
assert self.text is not None
|
||||
mapping = {
|
||||
'smart': not self.text.islower(),
|
||||
'never': True,
|
||||
@ -280,8 +298,10 @@ class AbstractSearch(QObject):
|
||||
}
|
||||
return mapping[ignore_case]
|
||||
|
||||
def search(self, text, *, ignore_case='never', reverse=False,
|
||||
result_cb=None):
|
||||
def search(self, text: str, *,
|
||||
ignore_case: str = 'never',
|
||||
reverse: bool = False,
|
||||
result_cb: _Callback = None) -> None:
|
||||
"""Find the given text on the page.
|
||||
|
||||
Args:
|
||||
@ -292,11 +312,11 @@ class AbstractSearch(QObject):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def clear(self):
|
||||
def clear(self) -> None:
|
||||
"""Clear the current search."""
|
||||
raise NotImplementedError
|
||||
|
||||
def prev_result(self, *, result_cb=None):
|
||||
def prev_result(self, *, result_cb: _Callback = None) -> None:
|
||||
"""Go to the previous result of the current search.
|
||||
|
||||
Args:
|
||||
@ -304,7 +324,7 @@ class AbstractSearch(QObject):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def next_result(self, *, result_cb=None):
|
||||
def next_result(self, *, result_cb: _Callback = None) -> None:
|
||||
"""Go to the next result of the current search.
|
||||
|
||||
Args:
|
||||
@ -322,7 +342,7 @@ class AbstractZoom(QObject):
|
||||
_default_zoom_changed: Whether the zoom was changed from the default.
|
||||
"""
|
||||
|
||||
def __init__(self, tab, parent=None):
|
||||
def __init__(self, tab: 'AbstractTab', parent: QWidget = None) -> None:
|
||||
super().__init__(parent)
|
||||
self._tab = tab
|
||||
self._widget = None
|
||||
@ -339,21 +359,21 @@ class AbstractZoom(QObject):
|
||||
# cfg.changed.disconnect, self.init_neighborlist))
|
||||
|
||||
@pyqtSlot(str)
|
||||
def _on_config_changed(self, option):
|
||||
def _on_config_changed(self, option: str) -> None:
|
||||
if option in ['zoom.levels', 'zoom.default']:
|
||||
if not self._default_zoom_changed:
|
||||
factor = float(config.val.zoom.default) / 100
|
||||
self.set_factor(factor)
|
||||
self._init_neighborlist()
|
||||
|
||||
def _init_neighborlist(self):
|
||||
def _init_neighborlist(self) -> None:
|
||||
"""Initialize self._neighborlist."""
|
||||
levels = config.val.zoom.levels
|
||||
self._neighborlist = usertypes.NeighborList(
|
||||
levels, mode=usertypes.NeighborList.Modes.edge)
|
||||
self._neighborlist.fuzzyval = config.val.zoom.default
|
||||
|
||||
def offset(self, offset):
|
||||
def offset(self, offset: int) -> None:
|
||||
"""Increase/Decrease the zoom level by the given offset.
|
||||
|
||||
Args:
|
||||
@ -366,10 +386,10 @@ class AbstractZoom(QObject):
|
||||
self.set_factor(float(level) / 100, fuzzyval=False)
|
||||
return level
|
||||
|
||||
def _set_factor_internal(self, factor):
|
||||
def _set_factor_internal(self, factor: float) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def set_factor(self, factor, *, fuzzyval=True):
|
||||
def set_factor(self, factor: float, *, fuzzyval: bool = True) -> None:
|
||||
"""Zoom to a given zoom factor.
|
||||
|
||||
Args:
|
||||
@ -387,13 +407,13 @@ class AbstractZoom(QObject):
|
||||
self._zoom_factor = factor
|
||||
self._set_factor_internal(factor)
|
||||
|
||||
def factor(self):
|
||||
def factor(self) -> float:
|
||||
return self._zoom_factor
|
||||
|
||||
def set_default(self):
|
||||
def set_default(self) -> None:
|
||||
self._set_factor_internal(float(config.val.zoom.default) / 100)
|
||||
|
||||
def set_current(self):
|
||||
def set_current(self) -> None:
|
||||
self._set_factor_internal(self._zoom_factor)
|
||||
|
||||
|
||||
@ -410,7 +430,10 @@ class AbstractCaret(QObject):
|
||||
selection_toggled = pyqtSignal(bool)
|
||||
follow_selected_done = pyqtSignal()
|
||||
|
||||
def __init__(self, tab, mode_manager, parent=None):
|
||||
def __init__(self,
|
||||
tab: 'AbstractTab',
|
||||
mode_manager: modeman.ModeManager,
|
||||
parent: QWidget = None) -> None:
|
||||
super().__init__(parent)
|
||||
self._tab = tab
|
||||
self._widget = None
|
||||
@ -418,74 +441,74 @@ class AbstractCaret(QObject):
|
||||
mode_manager.entered.connect(self._on_mode_entered)
|
||||
mode_manager.left.connect(self._on_mode_left)
|
||||
|
||||
def _on_mode_entered(self, mode):
|
||||
def _on_mode_entered(self, mode: usertypes.KeyMode) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def _on_mode_left(self, mode):
|
||||
def _on_mode_left(self, mode: usertypes.KeyMode) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_next_line(self, count=1):
|
||||
def move_to_next_line(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_prev_line(self, count=1):
|
||||
def move_to_prev_line(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_next_char(self, count=1):
|
||||
def move_to_next_char(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_prev_char(self, count=1):
|
||||
def move_to_prev_char(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_end_of_word(self, count=1):
|
||||
def move_to_end_of_word(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_next_word(self, count=1):
|
||||
def move_to_next_word(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_prev_word(self, count=1):
|
||||
def move_to_prev_word(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_start_of_line(self):
|
||||
def move_to_start_of_line(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_end_of_line(self):
|
||||
def move_to_end_of_line(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_start_of_next_block(self, count=1):
|
||||
def move_to_start_of_next_block(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_start_of_prev_block(self, count=1):
|
||||
def move_to_start_of_prev_block(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_end_of_next_block(self, count=1):
|
||||
def move_to_end_of_next_block(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_end_of_prev_block(self, count=1):
|
||||
def move_to_end_of_prev_block(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_start_of_document(self):
|
||||
def move_to_start_of_document(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def move_to_end_of_document(self):
|
||||
def move_to_end_of_document(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def toggle_selection(self):
|
||||
def toggle_selection(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def drop_selection(self):
|
||||
def drop_selection(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def selection(self, callback):
|
||||
def selection(self, callback: typing.Callable[[str], None]) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def _follow_enter(self, tab):
|
||||
def _follow_enter(self, tab: bool) -> None:
|
||||
"""Follow a link by faking an enter press."""
|
||||
if tab:
|
||||
self._tab.key_press(Qt.Key_Enter, modifier=Qt.ControlModifier)
|
||||
else:
|
||||
self._tab.key_press(Qt.Key_Enter)
|
||||
|
||||
def follow_selected(self, *, tab=False):
|
||||
def follow_selected(self, *, tab: bool = False) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@ -495,69 +518,69 @@ class AbstractScroller(QObject):
|
||||
|
||||
perc_changed = pyqtSignal(int, int)
|
||||
|
||||
def __init__(self, tab, parent=None):
|
||||
def __init__(self, tab: 'AbstractTab', parent: QWidget = None):
|
||||
super().__init__(parent)
|
||||
self._tab = tab
|
||||
self._widget = None
|
||||
self._widget = None # type: typing.Optional[QWebEngineView]
|
||||
self.perc_changed.connect(self._log_scroll_pos_change)
|
||||
|
||||
@pyqtSlot()
|
||||
def _log_scroll_pos_change(self):
|
||||
log.webview.vdebug("Scroll position changed to {}".format(
|
||||
self.pos_px()))
|
||||
def _log_scroll_pos_change(self) -> None:
|
||||
log.webview.vdebug( # type: ignore
|
||||
"Scroll position changed to {}".format(self.pos_px()))
|
||||
|
||||
def _init_widget(self, widget):
|
||||
def _init_widget(self, widget: 'QWebEngineView') -> None:
|
||||
self._widget = widget
|
||||
|
||||
def pos_px(self):
|
||||
def pos_px(self) -> int:
|
||||
raise NotImplementedError
|
||||
|
||||
def pos_perc(self):
|
||||
def pos_perc(self) -> int:
|
||||
raise NotImplementedError
|
||||
|
||||
def to_perc(self, x=None, y=None):
|
||||
def to_perc(self, x: int = None, y: int = None) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def to_point(self, point):
|
||||
def to_point(self, point: QPoint) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def to_anchor(self, name):
|
||||
def to_anchor(self, name: str) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def delta(self, x=0, y=0):
|
||||
def delta(self, x: int = 0, y: int = 0) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def delta_page(self, x=0, y=0):
|
||||
def delta_page(self, x: float = 0, y: float = 0) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def up(self, count=1):
|
||||
def up(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def down(self, count=1):
|
||||
def down(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def left(self, count=1):
|
||||
def left(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def right(self, count=1):
|
||||
def right(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def top(self):
|
||||
def top(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def bottom(self):
|
||||
def bottom(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def page_up(self, count=1):
|
||||
def page_up(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def page_down(self, count=1):
|
||||
def page_down(self, count: int = 1) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def at_top(self):
|
||||
def at_top(self) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def at_bottom(self):
|
||||
def at_bottom(self) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@ -565,20 +588,20 @@ class AbstractHistory:
|
||||
|
||||
"""The history attribute of a AbstractTab."""
|
||||
|
||||
def __init__(self, tab):
|
||||
def __init__(self, tab: 'AbstractTab') -> None:
|
||||
self._tab = tab
|
||||
self._history = None
|
||||
|
||||
def __len__(self):
|
||||
return len(self._history)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._history.items())
|
||||
|
||||
def current_idx(self):
|
||||
def __len__(self) -> int:
|
||||
raise NotImplementedError
|
||||
|
||||
def back(self, count=1):
|
||||
def __iter__(self) -> typing.Iterable:
|
||||
raise NotImplementedError
|
||||
|
||||
def current_idx(self) -> int:
|
||||
raise NotImplementedError
|
||||
|
||||
def back(self, count: int = 1) -> None:
|
||||
"""Go back in the tab's history."""
|
||||
idx = self.current_idx() - count
|
||||
if idx >= 0:
|
||||
@ -587,7 +610,7 @@ class AbstractHistory:
|
||||
self._go_to_item(self._item_at(0))
|
||||
raise WebTabError("At beginning of history.")
|
||||
|
||||
def forward(self, count=1):
|
||||
def forward(self, count: int = 1) -> None:
|
||||
"""Go forward in the tab's history."""
|
||||
idx = self.current_idx() + count
|
||||
if idx < len(self):
|
||||
@ -596,27 +619,27 @@ class AbstractHistory:
|
||||
self._go_to_item(self._item_at(len(self) - 1))
|
||||
raise WebTabError("At end of history.")
|
||||
|
||||
def can_go_back(self):
|
||||
def can_go_back(self) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def can_go_forward(self):
|
||||
def can_go_forward(self) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
def _item_at(self, i):
|
||||
def _item_at(self, i: int) -> typing.Any:
|
||||
raise NotImplementedError
|
||||
|
||||
def _go_to_item(self, item):
|
||||
def _go_to_item(self, item: typing.Any) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def serialize(self):
|
||||
def serialize(self) -> bytes:
|
||||
"""Serialize into an opaque format understood by self.deserialize."""
|
||||
raise NotImplementedError
|
||||
|
||||
def deserialize(self, data):
|
||||
"""Serialize from a format produced by self.serialize."""
|
||||
def deserialize(self, data: bytes) -> None:
|
||||
"""Deserialize from a format produced by self.serialize."""
|
||||
raise NotImplementedError
|
||||
|
||||
def load_items(self, items):
|
||||
def load_items(self, items: typing.Sequence) -> None:
|
||||
"""Deserialize from a list of WebHistoryItems."""
|
||||
raise NotImplementedError
|
||||
|
||||
@ -625,11 +648,18 @@ class AbstractElements:
|
||||
|
||||
"""Finding and handling of elements on the page."""
|
||||
|
||||
def __init__(self, tab):
|
||||
_MultiCallback = typing.Callable[
|
||||
[typing.Sequence[webelem.AbstractWebElement]], None]
|
||||
_SingleCallback = typing.Callable[
|
||||
[typing.Optional[webelem.AbstractWebElement]], None]
|
||||
|
||||
def __init__(self, tab: 'AbstractTab') -> None:
|
||||
self._widget = None
|
||||
self._tab = tab
|
||||
|
||||
def find_css(self, selector, callback, *, only_visible=False):
|
||||
def find_css(self, selector: str,
|
||||
callback: _MultiCallback, *,
|
||||
only_visible: bool = False) -> None:
|
||||
"""Find all HTML elements matching a given selector async.
|
||||
|
||||
If there's an error, the callback is called with a webelem.Error
|
||||
@ -642,7 +672,7 @@ class AbstractElements:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def find_id(self, elem_id, callback):
|
||||
def find_id(self, elem_id: str, callback: _SingleCallback) -> None:
|
||||
"""Find the HTML element with the given ID async.
|
||||
|
||||
Args:
|
||||
@ -651,7 +681,7 @@ class AbstractElements:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def find_focused(self, callback):
|
||||
def find_focused(self, callback: _SingleCallback) -> None:
|
||||
"""Find the focused element on the page async.
|
||||
|
||||
Args:
|
||||
@ -660,7 +690,7 @@ class AbstractElements:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def find_at_pos(self, pos, callback):
|
||||
def find_at_pos(self, pos: QPoint, callback: _SingleCallback) -> None:
|
||||
"""Find the element at the given position async.
|
||||
|
||||
This is also called "hit test" elsewhere.
|
||||
@ -680,9 +710,9 @@ class AbstractAudio(QObject):
|
||||
muted_changed = pyqtSignal(bool)
|
||||
recently_audible_changed = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, tab, parent=None):
|
||||
def __init__(self, tab: 'AbstractTab', parent: QWidget = None) -> None:
|
||||
super().__init__(parent)
|
||||
self._widget = None
|
||||
self._widget = None # type: typing.Optional[QWebEngineView]
|
||||
self._tab = tab
|
||||
|
||||
def set_muted(self, muted: bool, override: bool = False) -> None:
|
||||
@ -695,14 +725,14 @@ class AbstractAudio(QObject):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def is_muted(self):
|
||||
def is_muted(self) -> bool:
|
||||
"""Whether this tab is muted."""
|
||||
raise NotImplementedError
|
||||
|
||||
def toggle_muted(self, *, override: bool = False) -> None:
|
||||
self.set_muted(not self.is_muted(), override=override)
|
||||
|
||||
def is_recently_audible(self):
|
||||
def is_recently_audible(self) -> bool:
|
||||
"""Whether this tab has had audio playing recently."""
|
||||
raise NotImplementedError
|
||||
|
||||
@ -758,7 +788,11 @@ class AbstractTab(QWidget):
|
||||
renderer_process_terminated = pyqtSignal(TerminationStatus, int)
|
||||
predicted_navigation = pyqtSignal(QUrl)
|
||||
|
||||
def __init__(self, *, win_id, mode_manager, private, parent=None):
|
||||
def __init__(self, *,
|
||||
win_id: int,
|
||||
mode_manager: modeman.ModeManager,
|
||||
private: bool,
|
||||
parent: QWidget = None) -> None:
|
||||
self.private = private
|
||||
self.win_id = win_id
|
||||
self.tab_id = next(tab_id_gen)
|
||||
@ -772,7 +806,7 @@ class AbstractTab(QWidget):
|
||||
|
||||
self.data = TabData()
|
||||
self._layout = miscwidgets.WrapperLayout(self)
|
||||
self._widget = None
|
||||
self._widget = None # type: typing.Optional[QWebEngineView]
|
||||
self._progress = 0
|
||||
self._has_ssl_errors = False
|
||||
self._mode_manager = mode_manager
|
||||
@ -789,7 +823,7 @@ class AbstractTab(QWidget):
|
||||
|
||||
self.predicted_navigation.connect(self._on_predicted_navigation)
|
||||
|
||||
def _set_widget(self, widget):
|
||||
def _set_widget(self, widget: 'QWebEngineView') -> None:
|
||||
# pylint: disable=protected-access
|
||||
self._widget = widget
|
||||
self._layout.wrap(self, widget)
|
||||
@ -807,10 +841,10 @@ class AbstractTab(QWidget):
|
||||
self._install_event_filter()
|
||||
self.zoom.set_default()
|
||||
|
||||
def _install_event_filter(self):
|
||||
def _install_event_filter(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def _set_load_status(self, val):
|
||||
def _set_load_status(self, val: usertypes.LoadStatus) -> None:
|
||||
"""Setter for load_status."""
|
||||
if not isinstance(val, usertypes.LoadStatus):
|
||||
raise TypeError("Type {} is no LoadStatus member!".format(val))
|
||||
@ -818,11 +852,11 @@ class AbstractTab(QWidget):
|
||||
self._load_status = val
|
||||
self.load_status_changed.emit(val.name)
|
||||
|
||||
def event_target(self):
|
||||
def event_target(self) -> QWidget:
|
||||
"""Return the widget events should be sent to."""
|
||||
raise NotImplementedError
|
||||
|
||||
def send_event(self, evt):
|
||||
def send_event(self, evt: QEvent) -> None:
|
||||
"""Send the given event to the underlying widget.
|
||||
|
||||
The event will be sent via QApplication.postEvent.
|
||||
@ -844,7 +878,7 @@ class AbstractTab(QWidget):
|
||||
QApplication.postEvent(recipient, evt)
|
||||
|
||||
@pyqtSlot(QUrl)
|
||||
def _on_predicted_navigation(self, url):
|
||||
def _on_predicted_navigation(self, url: QUrl) -> None:
|
||||
"""Adjust the title if we are going to visit a URL soon."""
|
||||
qtutils.ensure_valid(url)
|
||||
url_string = url.toDisplayString()
|
||||
@ -852,14 +886,14 @@ class AbstractTab(QWidget):
|
||||
self.title_changed.emit(url_string)
|
||||
|
||||
@pyqtSlot(QUrl)
|
||||
def _on_url_changed(self, url):
|
||||
def _on_url_changed(self, url: QUrl) -> None:
|
||||
"""Update title when URL has changed and no title is available."""
|
||||
if url.isValid() and not self.title():
|
||||
self.title_changed.emit(url.toDisplayString())
|
||||
self.url_changed.emit(url)
|
||||
|
||||
@pyqtSlot()
|
||||
def _on_load_started(self):
|
||||
def _on_load_started(self) -> None:
|
||||
self._progress = 0
|
||||
self._has_ssl_errors = False
|
||||
self.data.viewing_source = False
|
||||
@ -867,7 +901,10 @@ class AbstractTab(QWidget):
|
||||
self.load_started.emit()
|
||||
|
||||
@pyqtSlot(usertypes.NavigationRequest)
|
||||
def _on_navigation_request(self, navigation):
|
||||
def _on_navigation_request(
|
||||
self,
|
||||
navigation: usertypes.NavigationRequest
|
||||
) -> None:
|
||||
"""Handle common acceptNavigationRequest code."""
|
||||
url = utils.elide(navigation.url.toDisplayString(), 100)
|
||||
log.webview.debug("navigation request: url {}, type {}, is_main_frame "
|
||||
@ -891,7 +928,7 @@ class AbstractTab(QWidget):
|
||||
navigation.url.errorString()))
|
||||
navigation.accepted = False
|
||||
|
||||
def handle_auto_insert_mode(self, ok):
|
||||
def handle_auto_insert_mode(self, ok: bool) -> None:
|
||||
"""Handle `input.insert_mode.auto_load` after loading finished."""
|
||||
if not config.val.input.insert_mode.auto_load or not ok:
|
||||
return
|
||||
@ -900,7 +937,7 @@ class AbstractTab(QWidget):
|
||||
if cur_mode == usertypes.KeyMode.insert:
|
||||
return
|
||||
|
||||
def _auto_insert_mode_cb(elem):
|
||||
def _auto_insert_mode_cb(elem: webelem.AbstractWebElement) -> None:
|
||||
"""Called from JS after finding the focused element."""
|
||||
if elem is None:
|
||||
log.webview.debug("No focused element!")
|
||||
@ -912,7 +949,8 @@ class AbstractTab(QWidget):
|
||||
self.elements.find_focused(_auto_insert_mode_cb)
|
||||
|
||||
@pyqtSlot(bool)
|
||||
def _on_load_finished(self, ok):
|
||||
def _on_load_finished(self, ok: bool) -> None:
|
||||
assert self._widget is not None
|
||||
if sip.isdeleted(self._widget):
|
||||
# https://github.com/qutebrowser/qutebrowser/issues/3498
|
||||
return
|
||||
@ -943,46 +981,50 @@ class AbstractTab(QWidget):
|
||||
self.zoom.set_current()
|
||||
|
||||
@pyqtSlot()
|
||||
def _on_history_trigger(self):
|
||||
def _on_history_trigger(self) -> None:
|
||||
"""Emit add_history_item when triggered by backend-specific signal."""
|
||||
raise NotImplementedError
|
||||
|
||||
@pyqtSlot(int)
|
||||
def _on_load_progress(self, perc):
|
||||
def _on_load_progress(self, perc: int) -> None:
|
||||
self._progress = perc
|
||||
self.load_progress.emit(perc)
|
||||
|
||||
def url(self, requested=False):
|
||||
def url(self, requested: bool = False) -> QUrl:
|
||||
raise NotImplementedError
|
||||
|
||||
def progress(self):
|
||||
def progress(self) -> int:
|
||||
return self._progress
|
||||
|
||||
def load_status(self):
|
||||
def load_status(self) -> usertypes.LoadStatus:
|
||||
return self._load_status
|
||||
|
||||
def _openurl_prepare(self, url, *, predict=True):
|
||||
def _openurl_prepare(self, url: QUrl, *, predict: bool = True) -> None:
|
||||
qtutils.ensure_valid(url)
|
||||
if predict:
|
||||
self.predicted_navigation.emit(url)
|
||||
|
||||
def openurl(self, url, *, predict=True):
|
||||
def openurl(self, url: QUrl, *, predict: bool = True) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def reload(self, *, force=False):
|
||||
def reload(self, *, force: bool = False) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def stop(self):
|
||||
def stop(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def clear_ssl_errors(self):
|
||||
def clear_ssl_errors(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def key_press(self, key, modifier=Qt.NoModifier):
|
||||
def key_press(self,
|
||||
key: Qt.Key,
|
||||
modifier: Qt.KeyboardModifier = Qt.NoModifier) -> None:
|
||||
"""Send a fake key event to this tab."""
|
||||
raise NotImplementedError
|
||||
|
||||
def dump_async(self, callback, *, plain=False):
|
||||
def dump_async(self,
|
||||
callback: typing.Callable[[str], None], *,
|
||||
plain: bool = False) -> None:
|
||||
"""Dump the current page's html asynchronously.
|
||||
|
||||
The given callback will be called with the result when dumping is
|
||||
@ -990,7 +1032,12 @@ class AbstractTab(QWidget):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def run_js_async(self, code, callback=None, *, world=None):
|
||||
def run_js_async(
|
||||
self,
|
||||
code: str,
|
||||
callback: typing.Callable[[typing.Any], None] = None, *,
|
||||
world: typing.Union[usertypes.JsWorld, int] = None
|
||||
) -> None:
|
||||
"""Run javascript async.
|
||||
|
||||
The given callback will be called with the result when running JS is
|
||||
@ -1004,19 +1051,19 @@ class AbstractTab(QWidget):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def shutdown(self):
|
||||
def shutdown(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def title(self):
|
||||
def title(self) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
def icon(self):
|
||||
def icon(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def set_html(self, html, base_url=QUrl()):
|
||||
def set_html(self, html: str, base_url: QUrl = QUrl()) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def networkaccessmanager(self):
|
||||
def networkaccessmanager(self) -> typing.Optional[QNetworkAccessManager]:
|
||||
"""Get the QNetworkAccessManager for this tab.
|
||||
|
||||
This is only implemented for QtWebKit.
|
||||
@ -1024,7 +1071,7 @@ class AbstractTab(QWidget):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def user_agent(self):
|
||||
def user_agent(self) -> typing.Optional[str]:
|
||||
"""Get the user agent for this tab.
|
||||
|
||||
This is only implemented for QtWebKit.
|
||||
@ -1032,13 +1079,16 @@ class AbstractTab(QWidget):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def __repr__(self):
|
||||
def __repr__(self) -> str:
|
||||
try:
|
||||
url = utils.elide(self.url().toDisplayString(QUrl.EncodeUnicode),
|
||||
100)
|
||||
qurl = self.url()
|
||||
url = qurl.toDisplayString(QUrl.EncodeUnicode) # type: ignore
|
||||
except (AttributeError, RuntimeError) as exc:
|
||||
url = '<{}>'.format(exc.__class__.__name__)
|
||||
else:
|
||||
url = utils.elide(url, 100)
|
||||
return utils.get_repr(self, tab_id=self.tab_id, url=url)
|
||||
|
||||
def is_deleted(self):
|
||||
def is_deleted(self) -> bool:
|
||||
assert self._widget is not None
|
||||
return sip.isdeleted(self._widget)
|
||||
|
@ -522,6 +522,12 @@ class WebEngineHistory(browsertab.AbstractHistory):
|
||||
|
||||
"""QtWebEngine implementations related to page history."""
|
||||
|
||||
def __len__(self):
|
||||
return len(self._history)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._history.items())
|
||||
|
||||
def current_idx(self):
|
||||
return self._history.currentItemIndex()
|
||||
|
||||
@ -551,7 +557,7 @@ class WebEngineHistory(browsertab.AbstractHistory):
|
||||
return qtutils.serialize(self._history)
|
||||
|
||||
def deserialize(self, data):
|
||||
return qtutils.deserialize(data, self._history)
|
||||
qtutils.deserialize(data, self._history)
|
||||
|
||||
def load_items(self, items):
|
||||
if items:
|
||||
@ -672,6 +678,7 @@ class WebEngineAudio(browsertab.AbstractAudio):
|
||||
|
||||
def set_muted(self, muted: bool, override: bool = False) -> None:
|
||||
self._overridden = override
|
||||
assert self._widget is not None
|
||||
page = self._widget.page()
|
||||
page.setAudioMuted(muted)
|
||||
|
||||
|
@ -513,6 +513,12 @@ class WebKitHistory(browsertab.AbstractHistory):
|
||||
|
||||
"""QtWebKit implementations related to page history."""
|
||||
|
||||
def __len__(self):
|
||||
return len(self._history)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._history.items())
|
||||
|
||||
def current_idx(self):
|
||||
return self._history.currentItemIndex()
|
||||
|
||||
@ -533,7 +539,7 @@ class WebKitHistory(browsertab.AbstractHistory):
|
||||
return qtutils.serialize(self._history)
|
||||
|
||||
def deserialize(self, data):
|
||||
return qtutils.deserialize(data, self._history)
|
||||
qtutils.deserialize(data, self._history)
|
||||
|
||||
def load_items(self, items):
|
||||
if items:
|
||||
|
Loading…
Reference in New Issue
Block a user