summaryrefslogtreecommitdiff
path: root/qutebrowser/browser
diff options
context:
space:
mode:
Diffstat (limited to 'qutebrowser/browser')
-rw-r--r--qutebrowser/browser/browsertab.py63
-rw-r--r--qutebrowser/browser/commands.py1
-rw-r--r--qutebrowser/browser/downloadview.py17
-rw-r--r--qutebrowser/browser/hints.py8
-rw-r--r--qutebrowser/browser/inspector.py16
-rw-r--r--qutebrowser/browser/network/pac.py3
-rw-r--r--qutebrowser/browser/qtnetworkdownloads.py3
-rw-r--r--qutebrowser/browser/qutescheme.py4
-rw-r--r--qutebrowser/browser/webengine/notification.py6
-rw-r--r--qutebrowser/browser/webengine/webenginedownloads.py8
-rw-r--r--qutebrowser/browser/webengine/webengineelem.py4
-rw-r--r--qutebrowser/browser/webengine/webengineinspector.py11
-rw-r--r--qutebrowser/browser/webengine/webenginequtescheme.py2
-rw-r--r--qutebrowser/browser/webengine/webenginesettings.py7
-rw-r--r--qutebrowser/browser/webengine/webenginetab.py34
-rw-r--r--qutebrowser/browser/webengine/webview.py4
-rw-r--r--qutebrowser/browser/webkit/network/networkreply.py21
-rw-r--r--qutebrowser/browser/webkit/webkitinspector.py4
-rw-r--r--qutebrowser/browser/webkit/webkittab.py76
-rw-r--r--qutebrowser/browser/webkit/webpage.py10
-rw-r--r--qutebrowser/browser/webkit/webview.py4
21 files changed, 200 insertions, 106 deletions
diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py
index 661c5f68b..699fe1b0b 100644
--- a/qutebrowser/browser/browsertab.py
+++ b/qutebrowser/browser/browsertab.py
@@ -24,7 +24,7 @@ import itertools
import functools
import dataclasses
from typing import (cast, TYPE_CHECKING, Any, Callable, Iterable, List, Optional,
- Sequence, Set, Type, Union)
+ Sequence, Set, Type, Union, Tuple)
from PyQt5.QtCore import (pyqtSignal, pyqtSlot, QUrl, QObject, QSizeF, Qt,
QEvent, QPoint, QRect)
@@ -35,12 +35,12 @@ from PyQt5.QtNetwork import QNetworkAccessManager
if TYPE_CHECKING:
from PyQt5.QtWebKit import QWebHistory, QWebHistoryItem
- from PyQt5.QtWebKitWidgets import QWebPage
+ from PyQt5.QtWebKitWidgets import QWebPage, QWebView
from PyQt5.QtWebEngineWidgets import (
- QWebEngineHistory, QWebEngineHistoryItem, QWebEnginePage)
+ QWebEngineHistory, QWebEngineHistoryItem, QWebEnginePage, QWebEngineView)
from qutebrowser.keyinput import modeman
-from qutebrowser.config import config
+from qutebrowser.config import config, websettings
from qutebrowser.utils import (utils, objreg, usertypes, log, qtutils,
urlutils, message, jinja)
from qutebrowser.misc import miscwidgets, objects, sessions
@@ -53,6 +53,7 @@ if TYPE_CHECKING:
tab_id_gen = itertools.count(0)
+_WidgetType = Union["QWebView", "QWebEngineView"]
def create(win_id: int,
@@ -156,7 +157,7 @@ class AbstractAction:
action_base: Type[Union['QWebPage.WebAction', 'QWebEnginePage.WebAction']]
def __init__(self, tab: 'AbstractTab') -> None:
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
self._tab = tab
def exit_fullscreen(self) -> None:
@@ -172,6 +173,7 @@ class AbstractAction:
member = getattr(self.action_class, name, None)
if not isinstance(member, self.action_base):
raise WebTabError("{} is not a valid web action!".format(name))
+ assert member is not None # for mypy
self._widget.triggerPageAction(member)
def show_source(self, pygments: bool = False) -> None:
@@ -229,7 +231,7 @@ class AbstractPrinting:
"""Attribute ``printing`` of AbstractTab for printing the page."""
def __init__(self, tab: 'AbstractTab') -> None:
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
self._tab = tab
def check_pdf_support(self) -> None:
@@ -308,7 +310,7 @@ class AbstractSearch(QObject):
def __init__(self, tab: 'AbstractTab', parent: QWidget = None):
super().__init__(parent)
self._tab = tab
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
self.text: Optional[str] = None
self.search_displayed = False
@@ -372,7 +374,7 @@ class AbstractZoom(QObject):
def __init__(self, tab: 'AbstractTab', parent: QWidget = None) -> None:
super().__init__(parent)
self._tab = tab
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
# Whether zoom was changed from the default.
self._default_zoom_changed = False
self._init_neighborlist()
@@ -466,7 +468,7 @@ class AbstractCaret(QObject):
mode_manager: modeman.ModeManager,
parent: QWidget = None) -> None:
super().__init__(parent)
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
self._mode_manager = mode_manager
mode_manager.entered.connect(self._on_mode_entered)
mode_manager.left.connect(self._on_mode_left)
@@ -559,7 +561,7 @@ class AbstractScroller(QObject):
def __init__(self, tab: 'AbstractTab', parent: QWidget = None):
super().__init__(parent)
self._tab = tab
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
if 'log-scroll-pos' in objects.debug_flags:
self.perc_changed.connect(self._log_scroll_pos_change)
@@ -568,16 +570,16 @@ class AbstractScroller(QObject):
log.webview.vdebug( # type: ignore[attr-defined]
"Scroll position changed to {}".format(self.pos_px()))
- def _init_widget(self, widget: QWidget) -> None:
+ def _init_widget(self, widget: _WidgetType) -> None:
self._widget = widget
- def pos_px(self) -> int:
+ def pos_px(self) -> QPoint:
raise NotImplementedError
- def pos_perc(self) -> int:
+ def pos_perc(self) -> Tuple[int, int]:
raise NotImplementedError
- def to_perc(self, x: int = None, y: int = None) -> None:
+ def to_perc(self, x: float = None, y: float = None) -> None:
raise NotImplementedError
def to_point(self, point: QPoint) -> None:
@@ -627,6 +629,8 @@ class AbstractHistoryPrivate:
"""Private API related to the history."""
+ _history: Union["QWebHistory", "QWebEngineHistory"]
+
def serialize(self) -> bytes:
"""Serialize into an opaque format understood by self.deserialize."""
raise NotImplementedError
@@ -711,7 +715,7 @@ class AbstractElements:
_ErrorCallback = Callable[[Exception], None]
def __init__(self, tab: 'AbstractTab') -> None:
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
self._tab = tab
def find_css(self, selector: str,
@@ -772,7 +776,7 @@ class AbstractAudio(QObject):
def __init__(self, tab: 'AbstractTab', parent: QWidget = None) -> None:
super().__init__(parent)
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
self._tab = tab
def set_muted(self, muted: bool, override: bool = False) -> None:
@@ -804,11 +808,11 @@ class AbstractTabPrivate:
def __init__(self, mode_manager: modeman.ModeManager,
tab: 'AbstractTab') -> None:
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
self._tab = tab
self._mode_manager = mode_manager
- def event_target(self) -> QWidget:
+ def event_target(self) -> Optional[QWidget]:
"""Return the widget events should be sent to."""
raise NotImplementedError
@@ -848,7 +852,7 @@ class AbstractTabPrivate:
def shutdown(self) -> None:
raise NotImplementedError
- def run_js_sync(self, code: str) -> None:
+ def run_js_sync(self, code: str) -> Any:
"""Run javascript sync.
Result will be returned when running JS is complete.
@@ -867,7 +871,7 @@ class AbstractTabPrivate:
self._tab.data.inspector = None
self.toggle_inspector(inspector.Position.window)
- def toggle_inspector(self, position: inspector.Position) -> None:
+ def toggle_inspector(self, position: Optional[inspector.Position]) -> None:
"""Show/hide (and if needed, create) the web inspector for this tab."""
tabdata = self._tab.data
if tabdata.inspector is None:
@@ -944,6 +948,19 @@ class AbstractTab(QWidget):
# for a given hostname anyways.
_insecure_hosts: Set[str] = set()
+ # Sub-APIs initialized by subclasses
+ history: AbstractHistory
+ scroller: AbstractScroller
+ caret: AbstractCaret
+ zoom: AbstractZoom
+ search: AbstractSearch
+ printing: AbstractPrinting
+ action: AbstractAction
+ elements: AbstractElements
+ audio: AbstractAudio
+ private_api: AbstractTabPrivate
+ settings: websettings.AbstractSettings
+
def __init__(self, *, win_id: int,
mode_manager: 'modeman.ModeManager',
private: bool,
@@ -962,7 +979,7 @@ class AbstractTab(QWidget):
self.data = TabData()
self._layout = miscwidgets.WrapperLayout(self)
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
self._progress = 0
self._load_status = usertypes.LoadStatus.none
self._tab_event_filter = eventfilter.TabEventFilter(
@@ -976,7 +993,7 @@ class AbstractTab(QWidget):
self.before_load_started.connect(self._on_before_load_started)
- def _set_widget(self, widget: QWidget) -> None:
+ def _set_widget(self, widget: Union["QWebView", "QWebEngineView"]) -> None:
# pylint: disable=protected-access
self._widget = widget
self.data.splitter = miscwidgets.InspectorSplitter(
@@ -1195,7 +1212,7 @@ class AbstractTab(QWidget):
def title(self) -> str:
raise NotImplementedError
- def icon(self) -> None:
+ def icon(self) -> QIcon:
raise NotImplementedError
def set_html(self, html: str, base_url: QUrl = QUrl()) -> None:
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
index 00d5e521f..7f9c4810d 100644
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -913,6 +913,7 @@ class CommandDispatcher:
# Not sure how you enter a command without an active window...
raise cmdutils.CommandError(
"No window specified and couldn't find active window!")
+ assert isinstance(active_win, mainwindow.MainWindow)
win_id = active_win.win_id
if win_id not in objreg.window_registry:
diff --git a/qutebrowser/browser/downloadview.py b/qutebrowser/browser/downloadview.py
index 69c58741a..8187a1002 100644
--- a/qutebrowser/browser/downloadview.py
+++ b/qutebrowser/browser/downloadview.py
@@ -86,6 +86,15 @@ class DownloadView(QListView):
count = model.rowCount()
return utils.get_repr(self, count=count)
+ def _model(self) -> downloads.DownloadModel:
+ """Get the current download model.
+
+ Ensures the model is not None.
+ """
+ model = self.model()
+ assert isinstance(model, downloads.DownloadModel), model
+ return model
+
@pyqtSlot()
def _update_geometry(self):
"""Wrapper to call updateGeometry.
@@ -112,7 +121,7 @@ class DownloadView(QListView):
"""
if not index.isValid():
return
- item = self.model().data(index, downloads.ModelRole.item)
+ item = self._model().data(index, downloads.ModelRole.item)
if item.done and item.successful:
item.open_file()
item.remove()
@@ -126,7 +135,7 @@ class DownloadView(QListView):
Args:
item: The DownloadItem to get the actions for, or None.
"""
- model = self.model()
+ model = self._model()
actions: _ActionListType = []
if item is None:
pass
@@ -154,7 +163,7 @@ class DownloadView(QListView):
"""Show the context menu."""
index = self.indexAt(point)
if index.isValid():
- item = self.model().data(index, downloads.ModelRole.item)
+ item = self._model().data(index, downloads.ModelRole.item)
else:
item = None
self._menu = QMenu(self)
@@ -176,7 +185,7 @@ class DownloadView(QListView):
def sizeHint(self):
"""Return sizeHint based on the view contents."""
- idx = self.model().last_index()
+ idx = self._model().last_index()
bottom = self.visualRect(idx).bottom()
if bottom != -1:
margins = self.contentsMargins()
diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py
index 2e4e8e4b4..335508b3d 100644
--- a/qutebrowser/browser/hints.py
+++ b/qutebrowser/browser/hints.py
@@ -255,7 +255,7 @@ class HintActions:
flags = QUrl.FullyEncoded | QUrl.RemovePassword
if url.scheme() == 'mailto':
flags |= QUrl.RemoveScheme
- urlstr = url.toString(flags) # type: ignore[arg-type]
+ urlstr = url.toString(flags)
new_content = urlstr
@@ -356,8 +356,7 @@ class HintActions:
url: The URL to open as a QUrl.
context: The HintContext to use.
"""
- urlstr = url.toString(
- QUrl.FullyEncoded | QUrl.RemovePassword) # type: ignore[arg-type]
+ urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
args = context.get_args(urlstr)
commandrunner = runners.CommandRunner(self._win_id)
commandrunner.run_safely('spawn ' + ' '.join(args))
@@ -657,6 +656,7 @@ class HintManager(QObject):
self._context.labels[string] = label
keyparser = self._get_keyparser(usertypes.KeyMode.hint)
+ assert isinstance(keyparser, modeparsers.HintKeyParser)
keyparser.update_bindings(strings)
modeman.enter(self._win_id, usertypes.KeyMode.hint,
@@ -852,6 +852,7 @@ class HintManager(QObject):
# apply auto_follow_timeout
timeout = config.val.hints.auto_follow_timeout
normal_parser = self._get_keyparser(usertypes.KeyMode.normal)
+ assert isinstance(normal_parser, modeparsers.NormalKeyParser)
normal_parser.set_inhibited_timeout(timeout)
# unpacking gets us the first (and only) key in the dict.
self._fire(*visible)
@@ -927,6 +928,7 @@ class HintManager(QObject):
self._context.labels[string] = label
keyparser = self._get_keyparser(usertypes.KeyMode.hint)
+ assert isinstance(keyparser, modeparsers.HintKeyParser)
keyparser.update_bindings(strings, preserve_filter=True)
# Note: filter_hints can be called with non-None filterstr only
diff --git a/qutebrowser/browser/inspector.py b/qutebrowser/browser/inspector.py
index 2b40e97e4..51cad3709 100644
--- a/qutebrowser/browser/inspector.py
+++ b/qutebrowser/browser/inspector.py
@@ -22,7 +22,7 @@
import base64
import binascii
import enum
-from typing import cast, Optional
+from typing import cast, Optional, Union, TYPE_CHECKING
from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent
@@ -34,6 +34,14 @@ from qutebrowser.utils import log, usertypes
from qutebrowser.keyinput import modeman
from qutebrowser.misc import miscwidgets
+if TYPE_CHECKING:
+ from PyQt5.QtWebKitWidgets import QWebInspector, QWebPage
+ from PyQt5.QtWebEngineWidgets import QWebEnginePage
+ from qutebrowser.browser.webengine import webengineinspector
+
+
+_WidgetType = Union["QWebInspector", "webengineinspector.WebEngineInspectorView"]
+
class Position(enum.Enum):
@@ -93,7 +101,7 @@ class AbstractWebInspector(QWidget):
win_id: int,
parent: QWidget = None) -> None:
super().__init__(parent)
- self._widget = cast(QWidget, None)
+ self._widget = cast(_WidgetType, None)
self._layout = miscwidgets.WrapperLayout(self)
self._splitter = splitter
self._position: Optional[Position] = None
@@ -105,7 +113,7 @@ class AbstractWebInspector(QWidget):
eventfilter=self._event_filter,
parent=self)
- def _set_widget(self, widget: QWidget) -> None:
+ def _set_widget(self, widget: _WidgetType) -> None:
self._widget = widget
self._widget.setWindowTitle("Web Inspector")
self._widget.installEventFilter(self._child_event_filter)
@@ -198,7 +206,7 @@ class AbstractWebInspector(QWidget):
geom = base64.b64encode(data).decode('ASCII')
configfiles.state['inspector']['window'] = geom
- def inspect(self, page: QWidget) -> None:
+ def inspect(self, page: Union["QWebPage", "QWebEnginePage"]) -> None:
"""Inspect the given QWeb(Engine)Page."""
raise NotImplementedError
diff --git a/qutebrowser/browser/network/pac.py b/qutebrowser/browser/network/pac.py
index 3a544c78f..99078ab20 100644
--- a/qutebrowser/browser/network/pac.py
+++ b/qutebrowser/browser/network/pac.py
@@ -270,8 +270,7 @@ class PACFetcher(QObject):
"""Fetch the proxy from the remote URL."""
assert self._manager is not None
self._reply = self._manager.get(QNetworkRequest(self._pac_url))
- self._reply.finished.connect( # type: ignore[attr-defined]
- self._finish)
+ self._reply.finished.connect(self._finish)
@pyqtSlot()
def _finish(self):
diff --git a/qutebrowser/browser/qtnetworkdownloads.py b/qutebrowser/browser/qtnetworkdownloads.py
index 8adb7ea20..a77289efb 100644
--- a/qutebrowser/browser/qtnetworkdownloads.py
+++ b/qutebrowser/browser/qtnetworkdownloads.py
@@ -24,7 +24,7 @@ import os.path
import shutil
import functools
import dataclasses
-from typing import Dict, IO, Optional
+from typing import Dict, IO, Optional, List
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QTimer, QUrl
from PyQt5.QtWidgets import QApplication
@@ -601,6 +601,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
"""
assert nam.adopted_downloads == 0
for download in self.downloads:
+ assert isinstance(download, DownloadItem)
if download._uses_nam(nam): # pylint: disable=protected-access
nam.adopt_download(download)
return nam.adopted_downloads
diff --git a/qutebrowser/browser/qutescheme.py b/qutebrowser/browser/qutescheme.py
index 68e36d249..c0da8ac94 100644
--- a/qutebrowser/browser/qutescheme.py
+++ b/qutebrowser/browser/qutescheme.py
@@ -128,9 +128,7 @@ def data_for_url(url: QUrl) -> Tuple[str, bytes]:
Return:
A (mimetype, data) tuple.
"""
- norm_url = url.adjusted(
- QUrl.NormalizePathSegments | # type: ignore[arg-type]
- QUrl.StripTrailingSlash)
+ norm_url = url.adjusted(QUrl.NormalizePathSegments | QUrl.StripTrailingSlash)
if norm_url != url:
raise Redirect(norm_url)
diff --git a/qutebrowser/browser/webengine/notification.py b/qutebrowser/browser/webengine/notification.py
index 2b77a5ac4..57b593ce1 100644
--- a/qutebrowser/browser/webengine/notification.py
+++ b/qutebrowser/browser/webengine/notification.py
@@ -288,7 +288,7 @@ class NotificationBridgePresenter(QObject):
qt_notification.show()
self._active_notifications[notification_id] = qt_notification
- qt_notification.closed.connect( # type: ignore[attr-defined]
+ qt_notification.closed.connect(
functools.partial(self._adapter.on_web_closed, notification_id))
def _find_replaces_id(
@@ -632,6 +632,7 @@ class HerbeNotificationAdapter(AbstractNotificationAdapter):
self.close_id.emit(pid)
else:
proc = self.sender()
+ assert isinstance(proc, QProcess), proc
stderr = proc.readAllStandardError()
raise Error(f'herbe exited with status {code}: {stderr}')
@@ -757,8 +758,7 @@ class DBusNotificationAdapter(AbstractNotificationAdapter):
QDBusServiceWatcher.WatchForUnregistration,
self,
)
- self._watcher.serviceUnregistered.connect( # type: ignore[attr-defined]
- self._on_service_unregistered)
+ self._watcher.serviceUnregistered.connect(self._on_service_unregistered)
test_service = 'test-notification-service' in objects.debug_flags
service = self.TEST_SERVICE if test_service else self.SERVICE
diff --git a/qutebrowser/browser/webengine/webenginedownloads.py b/qutebrowser/browser/webengine/webenginedownloads.py
index a6a2a1b93..a96f49d6b 100644
--- a/qutebrowser/browser/webengine/webenginedownloads.py
+++ b/qutebrowser/browser/webengine/webenginedownloads.py
@@ -44,10 +44,8 @@ class DownloadItem(downloads.AbstractDownloadItem):
parent: QObject = None) -> None:
super().__init__(manager=manager, parent=manager)
self._qt_item = qt_item
- qt_item.downloadProgress.connect( # type: ignore[attr-defined]
- self.stats.on_download_progress)
- qt_item.stateChanged.connect( # type: ignore[attr-defined]
- self._on_state_changed)
+ qt_item.downloadProgress.connect(self.stats.on_download_progress)
+ qt_item.stateChanged.connect(self._on_state_changed)
# Ensure wrapped qt_item is deleted manually when the wrapper object
# is deleted. See https://github.com/qutebrowser/qutebrowser/issues/3373
@@ -92,7 +90,7 @@ class DownloadItem(downloads.AbstractDownloadItem):
def _do_die(self):
progress_signal = self._qt_item.downloadProgress
- progress_signal.disconnect() # type: ignore[attr-defined]
+ progress_signal.disconnect()
if self._qt_item.state() != QWebEngineDownloadItem.DownloadInterrupted:
self._qt_item.cancel()
diff --git a/qutebrowser/browser/webengine/webengineelem.py b/qutebrowser/browser/webengine/webengineelem.py
index 5d4c6ad9a..75b7a51ba 100644
--- a/qutebrowser/browser/webengine/webengineelem.py
+++ b/qutebrowser/browser/webengine/webengineelem.py
@@ -37,6 +37,8 @@ class WebEngineElement(webelem.AbstractWebElement):
"""A web element for QtWebEngine, using JS under the hood."""
+ _tab: "webenginetab.WebEngineTab"
+
def __init__(self, js_dict: Dict[str, Any],
tab: 'webenginetab.WebEngineTab') -> None:
super().__init__(tab)
@@ -248,7 +250,7 @@ class WebEngineElement(webelem.AbstractWebElement):
# (it does so with a 0ms QTimer...)
# This is also used in Qt's tests:
# https://github.com/qt/qtwebengine/commit/5e572e88efa7ba7c2b9138ec19e606d3e345ac90
- QApplication.processEvents( # type: ignore[call-overload]
+ QApplication.processEvents(
QEventLoop.ExcludeSocketNotifiers |
QEventLoop.ExcludeUserInputEvents)
diff --git a/qutebrowser/browser/webengine/webengineinspector.py b/qutebrowser/browser/webengine/webengineinspector.py
index ae31c0bee..d30a716de 100644
--- a/qutebrowser/browser/webengine/webengineinspector.py
+++ b/qutebrowser/browser/webengine/webengineinspector.py
@@ -49,13 +49,17 @@ class WebEngineInspectorView(QWebEngineView):
See WebEngineView.createWindow for details.
"""
- return self.page().inspectedPage().view().createWindow(wintype)
+ view = self.page().inspectedPage().view()
+ assert isinstance(view, QWebEngineView)
+ return view.createWindow(wintype)
class WebEngineInspector(inspector.AbstractWebInspector):
"""A web inspector for QtWebEngine with Qt API support."""
+ _widget: WebEngineInspectorView
+
def __init__(self, splitter: miscwidgets.InspectorSplitter,
win_id: int,
parent: QWidget = None) -> None:
@@ -66,8 +70,7 @@ class WebEngineInspector(inspector.AbstractWebInspector):
self._settings = webenginesettings.WebEngineSettings(view.settings())
self._set_widget(view)
page = view.page()
- page.windowCloseRequested.connect( # type: ignore[attr-defined]
- self._on_window_close_requested)
+ page.windowCloseRequested.connect(self._on_window_close_requested)
def _on_window_close_requested(self) -> None:
"""Called when the 'x' was clicked in the devtools."""
@@ -96,7 +99,7 @@ class WebEngineInspector(inspector.AbstractWebInspector):
"please install the qt5-qtwebengine-devtools "
"Fedora package.")
- def inspect(self, page: QWebEnginePage) -> None: # type: ignore[override]
+ def inspect(self, page: QWebEnginePage) -> None:
inspector_page = self._widget.page()
inspector_page.setInspectedPage(page)
self._settings.update_for_url(inspector_page.requestedUrl())
diff --git a/qutebrowser/browser/webengine/webenginequtescheme.py b/qutebrowser/browser/webengine/webenginequtescheme.py
index 64361f7c4..9e073951a 100644
--- a/qutebrowser/browser/webengine/webenginequtescheme.py
+++ b/qutebrowser/browser/webengine/webenginequtescheme.py
@@ -138,6 +138,6 @@ def init():
assert not QWebEngineUrlScheme.schemeByName(b'qute').name()
scheme = QWebEngineUrlScheme(b'qute')
scheme.setFlags(
- QWebEngineUrlScheme.LocalScheme | # type: ignore[arg-type]
+ QWebEngineUrlScheme.LocalScheme |
QWebEngineUrlScheme.LocalAccessAllowed)
QWebEngineUrlScheme.registerScheme(scheme)
diff --git a/qutebrowser/browser/webengine/webenginesettings.py b/qutebrowser/browser/webengine/webenginesettings.py
index 5430cec77..0b25726c0 100644
--- a/qutebrowser/browser/webengine/webenginesettings.py
+++ b/qutebrowser/browser/webengine/webenginesettings.py
@@ -332,9 +332,9 @@ class ProfileSetter:
def _update_settings(option):
"""Update global settings when qwebsettings changed."""
_global_settings.update_setting(option)
- default_profile.setter.update_setting(option)
+ default_profile.setter.update_setting(option) # type: ignore[attr-defined]
if private_profile:
- private_profile.setter.update_setting(option)
+ private_profile.setter.update_setting(option) # type: ignore[attr-defined]
def _init_user_agent_str(ua):
@@ -352,8 +352,9 @@ def _init_profile(profile: QWebEngineProfile) -> None:
This currently only contains the steps which are shared between a private and a
non-private profile (at the moment, only the default profile).
"""
+ # FIXME:mypy subclass QWebEngineProfile instead?
profile.setter = ProfileSetter(profile) # type: ignore[attr-defined]
- profile.setter.init_profile()
+ profile.setter.init_profile() # type: ignore[attr-defined]
_qute_scheme_handler.install(profile)
_req_interceptor.install(profile)
diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py
index 7d355d10e..28182d1b6 100644
--- a/qutebrowser/browser/webengine/webenginetab.py
+++ b/qutebrowser/browser/webengine/webenginetab.py
@@ -30,7 +30,7 @@ from PyQt5.QtCore import (pyqtSignal, pyqtSlot, Qt, QPoint, QPointF, QTimer, QUr
QObject)
from PyQt5.QtNetwork import QAuthenticator
from PyQt5.QtWidgets import QWidget
-from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineScript, QWebEngineHistory
+from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineView, QWebEngineScript, QWebEngineHistory
from qutebrowser.config import config
from qutebrowser.browser import browsertab, eventfilter, shared, webelem, greasemonkey
@@ -57,6 +57,8 @@ class WebEngineAction(browsertab.AbstractAction):
"""QtWebEngine implementations related to web actions."""
+ _widget: webview.WebEngineView
+
action_class = QWebEnginePage
action_base = QWebEnginePage.WebAction
@@ -79,6 +81,8 @@ class WebEnginePrinting(browsertab.AbstractPrinting):
"""QtWebEngine implementations related to printing."""
+ _widget: webview.WebEngineView
+
def check_pdf_support(self):
pass
@@ -190,6 +194,8 @@ class WebEngineSearch(browsertab.AbstractSearch):
_pending_searches: How many searches have been started but not called
back yet.
"""
+
+ _widget: webview.WebEngineView
def __init__(self, tab, parent=None):
super().__init__(tab, parent)
@@ -199,7 +205,7 @@ class WebEngineSearch(browsertab.AbstractSearch):
self._wrap_handler = _WebEngineSearchWrapHandler()
def _empty_flags(self):
- return QWebEnginePage.FindFlags(0) # type: ignore[call-overload]
+ return QWebEnginePage.FindFlags(0)
def _args_to_flags(self, reverse, ignore_case):
flags = self._empty_flags()
@@ -275,8 +281,7 @@ class WebEngineSearch(browsertab.AbstractSearch):
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)) # type: ignore[call-overload]
+ flags = QWebEnginePage.FindFlags(int(self._flags))
if flags & QWebEnginePage.FindBackward:
if self._wrap_handler.prevent_wrapping(going_up=False):
return
@@ -493,6 +498,8 @@ class WebEngineScroller(browsertab.AbstractScroller):
"""QtWebEngine implementations related to scrolling."""
+ _widget: webview.WebEngineView
+
def __init__(self, tab, parent=None):
super().__init__(tab, parent)
self._pos_perc = (0, 0)
@@ -713,6 +720,8 @@ class WebEngineZoom(browsertab.AbstractZoom):
"""QtWebEngine implementations related to zooming."""
+ _widget: webview.WebEngineView
+
def _set_factor_internal(self, factor):
self._widget.setZoomFactor(factor)
@@ -799,6 +808,8 @@ class WebEngineAudio(browsertab.AbstractAudio):
If that's the case, we leave it alone.
"""
+ _widget: webview.WebEngineView
+
def __init__(self, tab, parent=None):
super().__init__(tab, parent)
self._overridden = False
@@ -870,6 +881,8 @@ class _WebEnginePermissions(QObject):
"""Handling of various permission-related signals."""
+ _widget: webview.WebEngineView
+
# Using 0 as WORKAROUND for:
# https://www.riverbankcomputing.com/pipermail/pyqt/2019-July/041903.html
@@ -898,7 +911,7 @@ class _WebEnginePermissions(QObject):
def __init__(self, tab, parent=None):
super().__init__(parent)
self._tab = tab
- self._widget = cast(QWidget, None)
+ self._widget = cast(webview.WebEngineView, None)
assert self._options.keys() == self._messages.keys()
def connect_signals(self):
@@ -1033,10 +1046,12 @@ class _Quirk:
class _WebEngineScripts(QObject):
+ _widget: webview.WebEngineView
+
def __init__(self, tab, parent=None):
super().__init__(parent)
self._tab = tab
- self._widget = cast(QWidget, None)
+ self._widget = cast(webview.WebEngineView, None)
self._greasemonkey = greasemonkey.gm_manager
def connect_signals(self):
@@ -1240,6 +1255,8 @@ class WebEngineTabPrivate(browsertab.AbstractTabPrivate):
"""QtWebEngine-related methods which aren't part of the public API."""
+ _widget: webview.WebEngineView
+
def networkaccessmanager(self):
return None
@@ -1275,6 +1292,10 @@ class WebEngineTab(browsertab.AbstractTab):
abort_questions = pyqtSignal()
+ _widget: QWebEngineView
+ search: WebEngineSearch
+ audio: WebEngineAudio
+
def __init__(self, *, win_id, mode_manager, private, parent=None):
super().__init__(win_id=win_id,
mode_manager=mode_manager,
@@ -1685,6 +1706,7 @@ class WebEngineTab(browsertab.AbstractTab):
def _connect_signals(self):
view = self._widget
page = view.page()
+ assert isinstance(page, webview.WebEnginePage)
page.windowCloseRequested.connect(self.window_close_requested)
page.linkHovered.connect(self.link_hovered)
diff --git a/qutebrowser/browser/webengine/webview.py b/qutebrowser/browser/webengine/webview.py
index 76ce1a42e..6e72df014 100644
--- a/qutebrowser/browser/webengine/webview.py
+++ b/qutebrowser/browser/webengine/webview.py
@@ -70,7 +70,9 @@ class WebEngineView(QWebEngineView):
return self.focusProxy()
def shutdown(self):
- self.page().shutdown()
+ page = self.page()
+ assert isinstance(page, WebEnginePage)
+ page.shutdown()
def createWindow(self, wintype):
"""Called by Qt when a page wants to create a new window.
diff --git a/qutebrowser/browser/webkit/network/networkreply.py b/qutebrowser/browser/webkit/network/networkreply.py
index c1ead3209..d5c724d63 100644
--- a/qutebrowser/browser/webkit/network/networkreply.py
+++ b/qutebrowser/browser/webkit/network/networkreply.py
@@ -59,15 +59,9 @@ class FixedDataNetworkReply(QNetworkReply):
# For some reason, a segfault will be triggered if these lambdas aren't
# there.
# pylint: disable=unnecessary-lambda
- QTimer.singleShot(
- 0,
- lambda: self.metaDataChanged.emit()) # type: ignore[attr-defined]
- QTimer.singleShot(
- 0,
- lambda: self.readyRead.emit()) # type: ignore[attr-defined]
- QTimer.singleShot(
- 0,
- lambda: self.finished.emit()) # type: ignore[attr-defined]
+ QTimer.singleShot(0, lambda: self.metaDataChanged.emit())
+ QTimer.singleShot(0, lambda: self.readyRead.emit())
+ QTimer.singleShot(0, lambda: self.finished.emit())
@pyqtSlot()
def abort(self):
@@ -122,10 +116,8 @@ class ErrorNetworkReply(QNetworkReply):
# the device to avoid getting a warning.
self.setOpenMode(QIODevice.ReadOnly)
self.setError(error, errorstring)
- QTimer.singleShot(0, lambda:
- self.error.emit(error)) # type: ignore[attr-defined]
- QTimer.singleShot(0, lambda:
- self.finished.emit()) # type: ignore[attr-defined]
+ QTimer.singleShot(0, lambda: self.error.emit(error))
+ QTimer.singleShot(0, lambda: self.finished.emit())
def abort(self):
"""Do nothing since it's a fake reply."""
@@ -152,8 +144,7 @@ class RedirectNetworkReply(QNetworkReply):
def __init__(self, new_url, parent=None):
super().__init__(parent)
self.setAttribute(QNetworkRequest.RedirectionTargetAttribute, new_url)
- QTimer.singleShot(0, lambda:
- self.finished.emit()) # type: ignore[attr-defined]
+ QTimer.singleShot(0, lambda: self.finished.emit())
def abort(self):
"""Called when there's e.g. a redirection limit."""
diff --git a/qutebrowser/browser/webkit/webkitinspector.py b/qutebrowser/browser/webkit/webkitinspector.py
index 57bcd40ea..2d4b95caf 100644
--- a/qutebrowser/browser/webkit/webkitinspector.py
+++ b/qutebrowser/browser/webkit/webkitinspector.py
@@ -31,6 +31,8 @@ class WebKitInspector(inspector.AbstractWebInspector):
"""A web inspector for QtWebKit."""
+ _widget = QWebInspector
+
def __init__(self, splitter: miscwidgets.InspectorSplitter,
win_id: int,
parent: QWidget = None) -> None:
@@ -38,7 +40,7 @@ class WebKitInspector(inspector.AbstractWebInspector):
qwebinspector = QWebInspector()
self._set_widget(qwebinspector)
- def inspect(self, page: QWebPage) -> None: # type: ignore[override]
+ def inspect(self, page: QWebPage) -> None:
settings = QWebSettings.globalSettings()
settings.setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
self._widget.setPage(page)
diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py
index 7a41b995c..6be096acf 100644
--- a/qutebrowser/browser/webkit/webkittab.py
+++ b/qutebrowser/browser/webkit/webkittab.py
@@ -32,8 +32,9 @@ from PyQt5.QtWebKit import QWebSettings, QWebHistory, QWebElement
from PyQt5.QtPrintSupport import QPrinter
from qutebrowser.browser import browsertab, shared
-from qutebrowser.browser.webkit import (webview, tabhistory, webkitelem,
+from qutebrowser.browser.webkit import (webview, webpage, tabhistory, webkitelem,
webkitsettings, webkitinspector)
+from qutebrowser.browser.webkit.network import networkmanager
from qutebrowser.utils import qtutils, usertypes, utils, log, debug, resources
from qutebrowser.keyinput import modeman
from qutebrowser.qt import sip
@@ -46,6 +47,8 @@ class WebKitAction(browsertab.AbstractAction):
action_class = QWebPage
action_base = QWebPage.WebAction
+ _widget: webview.WebView
+
def exit_fullscreen(self):
raise browsertab.UnsupportedOperationError
@@ -69,7 +72,7 @@ class WebKitAction(browsertab.AbstractAction):
'Unselect': QWebPage.ToggleVideoFullscreen + 2,
}
if name in new_actions:
- self._widget.triggerPageAction(new_actions[name])
+ self._widget.triggerPageAction(new_actions[name]) # type: ignore[arg-type]
return
super().run_string(name)
@@ -79,6 +82,8 @@ class WebKitPrinting(browsertab.AbstractPrinting):
"""QtWebKit implementations related to printing."""
+ _widget: webview.WebView
+
def check_pdf_support(self):
pass
@@ -101,6 +106,8 @@ class WebKitSearch(browsertab.AbstractSearch):
"""QtWebKit implementations related to searching on the page."""
+ _widget: webview.WebView
+
def __init__(self, tab, parent=None):
super().__init__(tab, parent)
self._flags = self._empty_flags()
@@ -153,7 +160,8 @@ class WebKitSearch(browsertab.AbstractSearch):
self.search_displayed = False
# We first clear the marked text, then the highlights
self._widget.findText('')
- self._widget.findText('', QWebPage.HighlightAllOccurrences)
+ self._widget.findText(
+ '', QWebPage.HighlightAllOccurrences) # type: ignore[arg-type]
def search(self, text, *, ignore_case=usertypes.IgnoreCase.never,
reverse=False, wrap=True, result_cb=None):
@@ -179,7 +187,7 @@ class WebKitSearch(browsertab.AbstractSearch):
def next_result(self, *, result_cb=None):
self.search_displayed = True
- found = self._widget.findText(self.text, self._flags)
+ found = self._widget.findText(self.text, self._flags) # type: ignore[arg-type]
self._call_cb(result_cb, found, self.text, self._flags, 'next_result')
def prev_result(self, *, result_cb=None):
@@ -191,7 +199,7 @@ class WebKitSearch(browsertab.AbstractSearch):
flags &= ~QWebPage.FindBackward
else:
flags |= QWebPage.FindBackward
- found = self._widget.findText(self.text, flags)
+ found = self._widget.findText(self.text, flags) # type: ignore[arg-type]
self._call_cb(result_cb, found, self.text, flags, 'prev_result')
@@ -199,6 +207,8 @@ class WebKitCaret(browsertab.AbstractCaret):
"""QtWebKit implementations related to moving the cursor/selection."""
+ _widget: webview.WebView
+
def __init__(self,
tab: 'WebKitTab',
mode_manager: modeman.ModeManager,
@@ -515,6 +525,8 @@ class WebKitZoom(browsertab.AbstractZoom):
"""QtWebKit implementations related to zooming."""
+ _widget: webview.WebView
+
def _set_factor_internal(self, factor):
self._widget.setZoomFactor(factor)
@@ -525,6 +537,8 @@ class WebKitScroller(browsertab.AbstractScroller):
# FIXME:qtwebengine When to use the main frame, when the current one?
+ _widget: webview.WebView
+
def pos_px(self):
return self._widget.page().mainFrame().scrollPosition()
@@ -624,6 +638,8 @@ class WebKitHistoryPrivate(browsertab.AbstractHistoryPrivate):
"""History-related methods which are not part of the extension API."""
+ _history: QWebHistory
+
def __init__(self, tab: 'WebKitTab') -> None:
self._tab = tab
self._history = cast(QWebHistory, None)
@@ -695,6 +711,7 @@ class WebKitElements(browsertab.AbstractElements):
"""QtWebKit implementations related to elements on the page."""
_tab: 'WebKitTab'
+ _widget: webview.WebView
def find_css(self, selector, callback, error_cb, *, only_visible=False):
utils.unused(error_cb)
@@ -730,7 +747,7 @@ class WebKitElements(browsertab.AbstractElements):
self.find_css('#' + elem_id, find_id_cb, error_cb=lambda exc: None)
def find_focused(self, callback):
- frame = self._widget.page().currentFrame()
+ frame = cast(Optional[QWebFrame], self._widget.page().currentFrame())
if frame is None:
callback(None)
return
@@ -744,7 +761,7 @@ class WebKitElements(browsertab.AbstractElements):
def find_at_pos(self, pos, callback):
assert pos.x() >= 0
assert pos.y() >= 0
- frame = self._widget.page().frameAt(pos)
+ frame = cast(Optional[QWebFrame], self._widget.page().frameAt(pos))
if frame is None:
# This happens when we click inside the webview, but not actually
# on the QWebPage - for example when clicking the scrollbar
@@ -796,6 +813,8 @@ class WebKitTabPrivate(browsertab.AbstractTabPrivate):
"""QtWebKit-related methods which aren't part of the public API."""
+ _widget: webview.WebView
+
def networkaccessmanager(self):
return self._widget.page().networkAccessManager()
@@ -821,6 +840,8 @@ class WebKitTab(browsertab.AbstractTab):
"""A QtWebKit tab in the browser."""
+ _widget: webview.WebView
+
def __init__(self, *, win_id, mode_manager, private, parent=None):
super().__init__(win_id=win_id,
mode_manager=mode_manager,
@@ -912,6 +933,7 @@ class WebKitTab(browsertab.AbstractTab):
def _on_load_started(self):
super()._on_load_started()
nam = self._widget.page().networkAccessManager()
+ assert isinstance(nam, networkmanager.NetworkManager)
nam.netrc_used = False
# Make sure the icon is cleared when navigating to a page without one.
self.icon_changed.emit(QIcon())
@@ -929,7 +951,9 @@ class WebKitTab(browsertab.AbstractTab):
when using error pages... See
https://github.com/qutebrowser/qutebrowser/issues/84
"""
- self._on_load_finished(not self._widget.page().error_occurred)
+ page = self._widget.page()
+ assert isinstance(page, webpage.BrowserPage)
+ self._on_load_finished(not page.error_occurred)
@pyqtSlot()
def _on_webkit_icon_changed(self):
@@ -984,18 +1008,30 @@ class WebKitTab(browsertab.AbstractTab):
view = self._widget
page = view.page()
frame = page.mainFrame()
- page.windowCloseRequested.connect(self.window_close_requested)
- page.linkHovered.connect(self.link_hovered)
- page.loadProgress.connect(self._on_load_progress)
- frame.loadStarted.connect(self._on_load_started)
+ page.windowCloseRequested.connect( # type: ignore[attr-defined]
+ self.window_close_requested)
+ page.linkHovered.connect( # type: ignore[attr-defined]
+ self.link_hovered)
+ page.loadProgress.connect( # type: ignore[attr-defined]
+ self._on_load_progress)
+ frame.loadStarted.connect( # type: ignore[attr-defined]
+ self._on_load_started)
view.scroll_pos_changed.connect(self.scroller.perc_changed)
- view.titleChanged.connect(self.title_changed)
- view.urlChanged.connect(self._on_url_changed)
+ view.titleChanged.connect( # type: ignore[attr-defined]
+ self.title_changed)
+ view.urlChanged.connect( # type: ignore[attr-defined]
+ self._on_url_changed)
view.shutting_down.connect(self.shutting_down)
page.networkAccessManager().sslErrors.connect(self._on_ssl_errors)
- frame.loadFinished.connect(self._on_frame_load_finished)
- view.iconChanged.connect(self._on_webkit_icon_changed)
- page.frameCreated.connect(self._on_frame_created)
- frame.contentsSizeChanged.connect(self._on_contents_size_changed)
- frame.initialLayoutCompleted.connect(self._on_history_trigger)
- page.navigation_request.connect(self._on_navigation_request)
+ frame.loadFinished.connect( # type: ignore[attr-defined]
+ self._on_frame_load_finished)
+ view.iconChanged.connect( # type: ignore[attr-defined]
+ self._on_webkit_icon_changed)
+ page.frameCreated.connect( # type: ignore[attr-defined]
+ self._on_frame_created)
+ frame.contentsSizeChanged.connect( # type: ignore[attr-defined]
+ self._on_contents_size_changed)
+ frame.initialLayoutCompleted.connect( # type: ignore[attr-defined]
+ self._on_history_trigger)
+ page.navigation_request.connect( # type: ignore[attr-defined]
+ self._on_navigation_request)
diff --git a/qutebrowser/browser/webkit/webpage.py b/qutebrowser/browser/webkit/webpage.py
index ddbd78de2..0adc003d1 100644
--- a/qutebrowser/browser/webkit/webpage.py
+++ b/qutebrowser/browser/webkit/webpage.py
@@ -241,6 +241,7 @@ class BrowserPage(QWebPage):
if download_manager.has_downloads_with_nam(nam):
nam.setParent(download_manager)
else:
+ assert isinstance(nam, networkmanager.NetworkManager)
nam.shutdown()
def display_content(self, reply, mimetype):
@@ -371,11 +372,10 @@ class BrowserPage(QWebPage):
self.setFeaturePermission, frame, feature,
QWebPage.PermissionDeniedByUser)
- url = frame.url().adjusted(cast(QUrl.FormattingOptions,
- QUrl.RemoveUserInfo |
- QUrl.RemovePath |
- QUrl.RemoveQuery |
- QUrl.RemoveFragment))
+ url = frame.url().adjusted(QUrl.RemoveUserInfo | # type: ignore[operator]
+ QUrl.RemovePath |
+ QUrl.RemoveQuery |
+ QUrl.RemoveFragment)
question = shared.feature_permission(
url=url,
option=options[feature], msg=messages[feature],
diff --git a/qutebrowser/browser/webkit/webview.py b/qutebrowser/browser/webkit/webview.py
index 289e29920..e54c4af50 100644
--- a/qutebrowser/browser/webkit/webview.py
+++ b/qutebrowser/browser/webkit/webview.py
@@ -109,7 +109,9 @@ class WebView(QWebView):
settings = self.settings()
settings.setAttribute(QWebSettings.JavascriptEnabled, False)
self.stop()
- self.page().shutdown()
+ page = self.page()
+ assert isinstance(page, webpage.BrowserPage)
+ page.shutdown()
def createWindow(self, wintype):
"""Called by Qt when a page wants to create a new window.