Introduce the concept of a signal cache in browser.

The latest cur_* signal emitted by each tab will be re-emitted now when
this tab gets the focus. This should fix the problem with stale data in
the statusbar.
This commit is contained in:
Florian Bruhin 2014-02-05 14:01:16 +01:00
parent 31707a7dd4
commit 81da8b6aaa
2 changed files with 35 additions and 25 deletions

2
TODO
View File

@ -39,7 +39,7 @@ Minor features/bugs
=================== ===================
progress bar is often red progress bar is often red
titles are still weird (and not attached to tab obj) titles are still weird
Hiding scrollbars Hiding scrollbars
All kind of FIXMEs All kind of FIXMEs
:bind :bind

View File

@ -6,6 +6,7 @@ containing BrowserTabs).
import logging import logging
from collections import OrderedDict
from PyQt5.QtWidgets import QShortcut, QApplication, QSizePolicy from PyQt5.QtWidgets import QShortcut, QApplication, QSizePolicy
from PyQt5.QtCore import pyqtSignal, Qt, QEvent from PyQt5.QtCore import pyqtSignal, Qt, QEvent
@ -24,13 +25,18 @@ class TabbedBrowser(TabWidget):
Provides methods to manage tabs, convenience methods to interact with the Provides methods to manage tabs, convenience methods to interact with the
current tab (cur_*) and filters signals to re-emit them when they occured current tab (cur_*) and filters signals to re-emit them when they occured
in the currently visible tab. in the currently visible tab.
For all tab-specific signals (cur_*) emitted by a tab, this happens:
- the signal gets added to a signal_cache of the tab, so it can be
emitted again if the current tab changes.
- the signal gets filtered with _filter_signals and self.cur_* gets
emitted if the signal occured in the current tab.
""" """
cur_progress = pyqtSignal(int) # Progress of the current tab changed cur_progress = pyqtSignal(int) # Progress of the current tab changed
cur_load_started = pyqtSignal() # Current tab started loading cur_load_started = pyqtSignal() # Current tab started loading
cur_load_finished = pyqtSignal(bool) # Current tab finished loading cur_load_finished = pyqtSignal(bool) # Current tab finished loading
cur_statusbar_message = pyqtSignal(str) # Status bar message cur_statusbar_message = pyqtSignal(str) # Status bar message
# FIXME we need to store this in our browser object
# Current tab changed scroll position # Current tab changed scroll position
cur_scroll_perc_changed = pyqtSignal(int, int) cur_scroll_perc_changed = pyqtSignal(int, int)
keypress = pyqtSignal('QKeyEvent') keypress = pyqtSignal('QKeyEvent')
@ -55,7 +61,6 @@ class TabbedBrowser(TabWidget):
tab.openurl(url) tab.openurl(url)
self.addTab(tab, url.url()) self.addTab(tab, url.url())
self.setCurrentWidget(tab) self.setCurrentWidget(tab)
self.cur_progress.emit(tab.progress)
tab.loadProgress.connect( tab.loadProgress.connect(
lambda *args: self._filter_signals(self.cur_progress, *args)) lambda *args: self._filter_signals(self.cur_progress, *args))
tab.loadFinished.connect( tab.loadFinished.connect(
@ -66,7 +71,9 @@ class TabbedBrowser(TabWidget):
tab.statusBarMessage.connect( tab.statusBarMessage.connect(
lambda *args: self._filter_signals(self.cur_statusbar_message, lambda *args: self._filter_signals(self.cur_statusbar_message,
*args)) *args))
tab.scroll_pos_changed.connect(self._scroll_pos_changed_handler) tab.scroll_pos_changed.connect(
lambda *args: self._filter_signals(self.cur_scroll_perc_changed,
*args))
# FIXME should we really bind this to loadStarted? Sometimes the URL # FIXME should we really bind this to loadStarted? Sometimes the URL
# isn't set correctly at this point, e.g. when doing # isn't set correctly at this point, e.g. when doing
# setContent(..., baseUrl=QUrl('foo')) # setContent(..., baseUrl=QUrl('foo'))
@ -327,12 +334,21 @@ class TabbedBrowser(TabWidget):
The original signal does not matter, since we get the new signal and The original signal does not matter, since we get the new signal and
all args. all args.
The current value of the signal is also stored in tab.signal_cache so
it can be emitted later when the tab changes to the current tab.
signal -- The signal to emit if the sender was the current widget. signal -- The signal to emit if the sender was the current widget.
*args -- The args to pass to the signal. *args -- The args to pass to the signal.
""" """
dbgstr = "{} ({})".format( dbgstr = "{} ({})".format(
signal.signal, ','.join([str(e) for e in args])) signal.signal, ','.join([str(e) for e in args]))
if self.currentWidget() == self.sender(): sender = self.sender()
if type(sender) != type(self.currentWidget()):
# FIXME why does this happen?
logging.warn('Got a signal to _filter_signals not by a tab!')
return
sender.signal_cache[signal.signal] = (signal, args)
if self.currentWidget() == sender:
logging.debug('{} - emitting'.format(dbgstr)) logging.debug('{} - emitting'.format(dbgstr))
return signal.emit(*args) return signal.emit(*args)
else: else:
@ -341,26 +357,14 @@ class TabbedBrowser(TabWidget):
def _currentChanged_handler(self, idx): def _currentChanged_handler(self, idx):
"""Update status bar values when a tab was changed. """Update status bar values when a tab was changed.
Slot for the currentChanged signal of any tab. Populates all signals from the signal cache.
"""
tab = self.widget(idx)
self.cur_progress.emit(tab.progress)
def _scroll_pos_changed_handler(self, x, y): Slot for the currentChanged signal.
"""Get the new position from a BrowserTab. If it's the current tab,
calculate the percentage and emits cur_scroll_perc_changed.
Slot for the scroll_pos_changed signal of any tab.
""" """
sender = self.sender() for (sigstr, (signal, args)) in self.widget(idx).signal_cache.items():
if sender != self.currentWidget(): dbgstr = "{} ({})".format(sigstr, ','.join([str(e) for e in args]))
return logging.debug('signal cache: emitting {}'.format(dbgstr))
frame = sender.page().mainFrame() signal.emit(*args)
m = (frame.scrollBarMaximum(Qt.Horizontal),
frame.scrollBarMaximum(Qt.Vertical))
perc = (round(100 * x / m[0]) if m[0] != 0 else 0,
round(100 * y / m[1]) if m[1] != 0 else 0)
self.cur_scroll_perc_changed.emit(*perc)
class BrowserTab(QWebView): class BrowserTab(QWebView):
@ -373,6 +377,8 @@ class BrowserTab(QWebView):
open_tab = pyqtSignal('QUrl') open_tab = pyqtSignal('QUrl')
_scroll_pos = (-1, -1) _scroll_pos = (-1, -1)
_open_new_tab = False # open new tab for the next action _open_new_tab = False # open new tab for the next action
# dict of tab specific signals, and the values we last got from them.
signal_cache = OrderedDict()
def __init__(self, parent): def __init__(self, parent):
super().__init__(parent) super().__init__(parent)
@ -428,8 +434,12 @@ class BrowserTab(QWebView):
frame.scrollBarValue(Qt.Vertical)) frame.scrollBarValue(Qt.Vertical))
if self._scroll_pos != new_pos: if self._scroll_pos != new_pos:
logging.debug("Updating scroll position") logging.debug("Updating scroll position")
self.scroll_pos_changed.emit(*new_pos) frame = self.page().mainFrame()
self._scroll_pos = new_pos m = (frame.scrollBarMaximum(Qt.Horizontal),
frame.scrollBarMaximum(Qt.Vertical))
perc = (round(100 * new_pos[0] / m[0]) if m[0] != 0 else 0,
round(100 * new_pos[1] / m[1]) if m[1] != 0 else 0)
self.scroll_pos_changed.emit(*perc)
return super().eventFilter(watched, e) return super().eventFilter(watched, e)
def event(self, e): def event(self, e):