summaryrefslogtreecommitdiff
path: root/qutebrowser/mainwindow/tabbedbrowser.py
diff options
context:
space:
mode:
Diffstat (limited to 'qutebrowser/mainwindow/tabbedbrowser.py')
-rw-r--r--qutebrowser/mainwindow/tabbedbrowser.py79
1 files changed, 56 insertions, 23 deletions
diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py
index a96f6d583..840e69cd0 100644
--- a/qutebrowser/mainwindow/tabbedbrowser.py
+++ b/qutebrowser/mainwindow/tabbedbrowser.py
@@ -28,7 +28,7 @@ from typing import (
Any, Deque, List, Mapping, MutableMapping, MutableSequence, Optional, Tuple)
from PyQt5.QtWidgets import QSizePolicy, QWidget, QApplication
-from PyQt5.QtCore import pyqtSignal, pyqtSlot, QTimer, QUrl
+from PyQt5.QtCore import pyqtSignal, pyqtSlot, QTimer, QUrl, QPoint
from qutebrowser.config import config
from qutebrowser.keyinput import modeman
@@ -73,14 +73,14 @@ class TabDeque:
size = config.val.tabs.focus_stack_size
if size < 0:
size = None
- self._stack: Deque[weakref.ReferenceType[QWidget]] = collections.deque(
- maxlen=size)
+ self._stack: Deque[weakref.ReferenceType[browsertab.AbstractTab]] = (
+ collections.deque(maxlen=size))
# Items that have been removed from the primary stack.
- self._stack_deleted: List[weakref.ReferenceType[QWidget]] = []
+ self._stack_deleted: List[weakref.ReferenceType[browsertab.AbstractTab]] = []
self._ignore_next = False
self._keep_deleted_next = False
- def on_switch(self, old_tab: QWidget) -> None:
+ def on_switch(self, old_tab: browsertab.AbstractTab) -> None:
"""Record tab switch events."""
if self._ignore_next:
self._ignore_next = False
@@ -92,24 +92,29 @@ class TabDeque:
self._keep_deleted_next = False
self._stack.append(tab)
- def prev(self, cur_tab: QWidget) -> QWidget:
+ def prev(self, cur_tab: browsertab.AbstractTab) -> browsertab.AbstractTab:
"""Get the 'previous' tab in the stack.
Throws IndexError on failure.
"""
- tab: Optional[QWidget] = None
+ tab: Optional[browsertab.AbstractTab] = None
while tab is None or tab.pending_removal or tab is cur_tab:
tab = self._stack.pop()()
self._stack_deleted.append(weakref.ref(cur_tab))
self._ignore_next = True
return tab
- def next(self, cur_tab: QWidget, *, keep_overflow: bool = True) -> QWidget:
+ def next(
+ self,
+ cur_tab: browsertab.AbstractTab,
+ *,
+ keep_overflow: bool = True,
+ ) -> browsertab.AbstractTab:
"""Get the 'next' tab in the stack.
Throws IndexError on failure.
"""
- tab: Optional[QWidget] = None
+ tab: Optional[browsertab.AbstractTab] = None
while tab is None or tab.pending_removal or tab is cur_tab:
tab = self._stack_deleted.pop()()
# On next tab-switch, current tab will be added to stack as normal.
@@ -118,7 +123,7 @@ class TabDeque:
self._keep_deleted_next = True
return tab
- def last(self, cur_tab: QWidget) -> QWidget:
+ def last(self, cur_tab: browsertab.AbstractTab) -> browsertab.AbstractTab:
"""Get the last tab.
Throws IndexError on failure.
@@ -216,7 +221,11 @@ class TabbedBrowser(QWidget):
self.widget.tabCloseRequested.connect(self.on_tab_close_requested)
self.widget.new_tab_requested.connect(self.tabopen)
self.widget.currentChanged.connect(self._on_current_changed)
- self.cur_fullscreen_requested.connect(self.widget.tabBar().maybe_hide)
+
+ tabbar = self.widget.tabBar()
+ assert isinstance(tabbar, tabwidget.TabBar)
+ self.cur_fullscreen_requested.connect(tabbar.maybe_hide)
+
self.widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
# load_finished instead of load_started as WORKAROUND for
@@ -235,8 +244,8 @@ class TabbedBrowser(QWidget):
self._now_focused = None
self.search_text = None
self.search_options: Mapping[str, Any] = {}
- self._local_marks: MutableMapping[QUrl, MutableMapping[str, int]] = {}
- self._global_marks: MutableMapping[str, Tuple[int, QUrl]] = {}
+ self._local_marks: MutableMapping[QUrl, MutableMapping[str, QPoint]] = {}
+ self._global_marks: MutableMapping[str, Tuple[QPoint, QUrl]] = {}
self.default_window_icon = self.widget.window().windowIcon()
self.is_private = private
self.tab_deque = TabDeque()
@@ -373,6 +382,25 @@ class TabbedBrowser(QWidget):
tab.history_item_triggered.connect(
history.web_history.add_from_tab)
+ def _current_tab(self) -> browsertab.AbstractTab:
+ """Get the current browser tab.
+
+ Note: The assert ensures the current tab is never None.
+ """
+ tab = self.widget.currentWidget()
+ assert isinstance(tab, browsertab.AbstractTab), tab
+ return tab
+
+ def _tab_by_idx(self, idx: int) -> Optional[browsertab.AbstractTab]:
+ """Get a browser tab by index.
+
+ If no tab was found at the given index, None is returned.
+ """
+ tab = self.widget.widget(idx)
+ if tab is not None:
+ assert isinstance(tab, browsertab.AbstractTab), tab
+ return tab
+
def current_url(self):
"""Get the URL of the current tab.
@@ -503,13 +531,15 @@ class TabbedBrowser(QWidget):
]
only_one_tab_open = self.widget.count() == 1
if only_one_tab_open and last_close_replaces:
- no_history = len(self.widget.widget(0).history) == 1
+ tab = self._tab_by_idx(0)
+ assert tab is not None
+ no_history = len(tab.history) == 1
urls = {
'blank': QUrl('about:blank'),
'startpage': config.val.url.start_pages[0],
'default-page': config.val.url.default_page,
}
- first_tab_url = self.widget.widget(0).url()
+ first_tab_url = tab.url()
last_close_urlstr = urls[last_close].toString().rstrip('/')
first_tab_urlstr = first_tab_url.toString().rstrip('/')
last_close_url_used = first_tab_urlstr == last_close_urlstr
@@ -520,7 +550,8 @@ class TabbedBrowser(QWidget):
for entry in reversed(entries):
if use_current_tab:
- newtab = self.widget.widget(0)
+ newtab = self._tab_by_idx(0)
+ assert newtab is not None
use_current_tab = False
else:
newtab = self.tabopen(background=False, idx=entry.index)
@@ -540,14 +571,14 @@ class TabbedBrowser(QWidget):
if newtab or self.widget.currentWidget() is None:
self.tabopen(url, background=False)
else:
- self.widget.currentWidget().load_url(url)
+ self._current_tab().load_url(url)
@pyqtSlot(int)
def on_tab_close_requested(self, idx):
"""Close a tab via an index."""
- tab = self.widget.widget(idx)
+ tab = self._tab_by_idx(idx)
if tab is None:
- log.webview.debug( # type: ignore[unreachable]
+ log.webview.debug(
"Got invalid tab {} for index {}!".format(tab, idx))
return
self.tab_close_prompt_if_pinned(
@@ -820,6 +851,7 @@ class TabbedBrowser(QWidget):
mode in modeman.INPUT_MODES):
tab = self.widget.currentWidget()
if tab is not None:
+ assert isinstance(tab, browsertab.AbstractTab)
tab.data.input_mode = mode
@pyqtSlot(usertypes.KeyMode)
@@ -833,6 +865,7 @@ class TabbedBrowser(QWidget):
widget))
widget.setFocus()
if config.val.tabs.mode_on_change == 'restore':
+ assert isinstance(widget, browsertab.AbstractTab)
widget.data.input_mode = usertypes.KeyMode.normal
@pyqtSlot(int)
@@ -842,9 +875,9 @@ class TabbedBrowser(QWidget):
if idx == -1 or self.is_shutting_down:
# closing the last tab (before quitting) or shutting down
return
- tab = self.widget.widget(idx)
+ tab = self._tab_by_idx(idx)
if tab is None:
- log.webview.debug( # type: ignore[unreachable]
+ log.webview.debug(
"on_current_changed got called with invalid index {}"
.format(idx))
return
@@ -1022,7 +1055,7 @@ class TabbedBrowser(QWidget):
if key != "'":
message.error("Failed to set mark: url invalid")
return
- point = self.widget.currentWidget().scroller.pos_px()
+ point = self._current_tab().scroller.pos_px()
if key.isupper():
self._global_marks[key] = point, url
@@ -1043,7 +1076,7 @@ class TabbedBrowser(QWidget):
except qtutils.QtValueError:
urlkey = None
- tab = self.widget.currentWidget()
+ tab = self._current_tab()
if key.isupper():
if key in self._global_marks: