Make SignalCache an own class.
This commit is contained in:
parent
d4e69c955e
commit
c77589a821
@ -17,8 +17,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import re
|
||||
|
||||
from PyQt5.QtCore import pyqtRemoveInputHook
|
||||
|
||||
try:
|
||||
@ -27,22 +25,6 @@ except ImportError:
|
||||
from pdb import set_trace as pdb_set_trace
|
||||
|
||||
|
||||
def signal_name(sig):
|
||||
"""Return a cleaned up name of a signal."""
|
||||
m = re.match(r'[0-9]+(.*)\(.*\)', sig.signal)
|
||||
return m.group(1)
|
||||
|
||||
|
||||
def dbg_signal(sig, args):
|
||||
"""Return a string representation of a signal for debugging.
|
||||
|
||||
sig -- A pyqtSignal.
|
||||
args -- The arguments as list of strings.
|
||||
|
||||
"""
|
||||
return '{}({})'.format(signal_name(sig), ', '.join(map(str, args)))
|
||||
|
||||
|
||||
def set_trace():
|
||||
"""
|
||||
Set a tracepoint in the Python debugger that works with Qt.
|
||||
|
91
qutebrowser/utils/signals.py
Normal file
91
qutebrowser/utils/signals.py
Normal file
@ -0,0 +1,91 @@
|
||||
"""Utilities regarding signals."""
|
||||
|
||||
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||
#
|
||||
# This file is part of qutebrowser.
|
||||
#
|
||||
# qutebrowser is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# qutebrowser is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import re
|
||||
import logging
|
||||
from collections import OrderedDict
|
||||
|
||||
from PyQt5.QtCore import QObject
|
||||
|
||||
|
||||
def signal_name(sig):
|
||||
"""Return a cleaned up name of a signal."""
|
||||
m = re.match(r'[0-9]+(.*)\(.*\)', sig.signal)
|
||||
return m.group(1)
|
||||
|
||||
|
||||
def dbg_signal(sig, args):
|
||||
"""Return a string representation of a signal for debugging.
|
||||
|
||||
sig -- A pyqtSignal.
|
||||
args -- The arguments as list of strings.
|
||||
|
||||
"""
|
||||
return '{}({})'.format(signal_name(sig), ', '.join(map(str, args)))
|
||||
|
||||
|
||||
class SignalCache(QObject):
|
||||
|
||||
"""Cache signals emitted by an object, and re-emit them later."""
|
||||
|
||||
uncached = None
|
||||
signal_dict = None
|
||||
|
||||
def __init__(self, uncached=None):
|
||||
"""Create a new SignalCache.
|
||||
|
||||
uncached -- A list of signal names (as string) which should never be
|
||||
cached.
|
||||
|
||||
"""
|
||||
super().__init__()
|
||||
if uncached is None:
|
||||
self.uncached = []
|
||||
else:
|
||||
self.uncached = uncached
|
||||
self.signal_dict = OrderedDict()
|
||||
|
||||
def add(self, sig, args):
|
||||
"""Add a new signal to the signal cache.
|
||||
|
||||
If the signal doesn't need caching it will be ignored.
|
||||
If it's already in the cache, it'll be updated and moved to the front.
|
||||
If not, it will be added.
|
||||
|
||||
"""
|
||||
if not self._signal_needs_caching(sig):
|
||||
return
|
||||
had_signal = sig.signal in self.signal_dict
|
||||
self.signal_dict[sig.signal] = (sig, args)
|
||||
if had_signal:
|
||||
self.signal_dict.move_to_end(sig.signal)
|
||||
|
||||
def clear(self):
|
||||
"""Clear/purge the signal cache."""
|
||||
self.signal_dict.clear()
|
||||
|
||||
def replay(self):
|
||||
"""Replay all cached signals."""
|
||||
for (signal, args) in self.signal_dict.values():
|
||||
logging.debug('emitting {}'.format(dbg_signal(signal, args)))
|
||||
signal.emit(*args)
|
||||
|
||||
def _signal_needs_caching(self, signal):
|
||||
"""Return True if a signal should be cached, false otherwise."""
|
||||
return not signal_name(signal) in self.uncached
|
@ -24,7 +24,6 @@ containing BrowserTabs).
|
||||
|
||||
import logging
|
||||
import functools
|
||||
from collections import OrderedDict
|
||||
|
||||
from PyQt5.QtWidgets import QShortcut, QApplication, QSizePolicy
|
||||
from PyQt5.QtCore import pyqtSignal, Qt, QEvent
|
||||
@ -36,7 +35,7 @@ import qutebrowser.utils.about as about
|
||||
import qutebrowser.utils.config as config
|
||||
import qutebrowser.utils.url as urlutils
|
||||
from qutebrowser.widgets.tabbar import TabWidget
|
||||
from qutebrowser.utils.misc import dbg_signal, signal_name
|
||||
from qutebrowser.utils.signals import dbg_signal, SignalCache
|
||||
|
||||
|
||||
class TabbedBrowser(TabWidget):
|
||||
@ -69,7 +68,8 @@ class TabbedBrowser(TabWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
self.currentChanged.connect(self._currentChanged_handler)
|
||||
self.currentChanged.connect(lambda idx:
|
||||
self.widget(idx).signal_cache.replay())
|
||||
space = QShortcut(self)
|
||||
space.setKey(Qt.Key_Space)
|
||||
space.setContext(Qt.WidgetWithChildrenShortcut)
|
||||
@ -92,7 +92,8 @@ class TabbedBrowser(TabWidget):
|
||||
tab.linkHovered.connect(self._filter_factory(self.cur_link_hovered))
|
||||
tab.loadProgress.connect(self._filter_factory(self.cur_progress))
|
||||
tab.loadFinished.connect(self._filter_factory(self.cur_load_finished))
|
||||
tab.loadStarted.connect(self._clear_signal_cache)
|
||||
tab.loadStarted.connect(lambda: # pylint: disable=unnecessary-lambda
|
||||
self.sender().signal_cache.clear())
|
||||
tab.loadStarted.connect(self._filter_factory(self.cur_load_started))
|
||||
tab.statusBarMessage.connect(
|
||||
self._filter_factory(self.cur_statusbar_message))
|
||||
@ -412,19 +413,7 @@ class TabbedBrowser(TabWidget):
|
||||
logging.warn('Got signal {} by {} which is no tab!'.format(
|
||||
dbg_signal(signal, args), sender))
|
||||
return
|
||||
if (signal.signal in sender.signal_cache and
|
||||
self._signal_needs_caching(signal)):
|
||||
if log_signal:
|
||||
logging.debug(" Moving to the end of signal cache")
|
||||
sender.signal_cache[signal.signal] = (signal, args)
|
||||
sender.signal_cache.move_to_end(signal.signal)
|
||||
elif self._signal_needs_caching(signal):
|
||||
if log_signal:
|
||||
logging.debug(" Adding to signal cache")
|
||||
sender.signal_cache[signal.signal] = (signal, args)
|
||||
else:
|
||||
if log_signal:
|
||||
logging.debug(" Ignoring for signal cache")
|
||||
sender.signal_cache.add(signal, args)
|
||||
if self.currentWidget() == sender:
|
||||
if log_signal:
|
||||
logging.debug(' emitting')
|
||||
@ -433,31 +422,6 @@ class TabbedBrowser(TabWidget):
|
||||
if log_signal:
|
||||
logging.debug(' ignoring')
|
||||
|
||||
def _currentChanged_handler(self, idx):
|
||||
"""Update status bar values when a tab was changed.
|
||||
|
||||
Populates all signals from the signal cache.
|
||||
|
||||
Slot for the currentChanged signal.
|
||||
|
||||
"""
|
||||
for (signal, args) in self.widget(idx).signal_cache.values():
|
||||
logging.debug('signal cache: emitting {} for tab {}'.format(
|
||||
dbg_signal(signal, args), idx))
|
||||
signal.emit(*args)
|
||||
|
||||
def _clear_signal_cache(self):
|
||||
"""Clear the signal cache of the sender of the signal."""
|
||||
sender = self.sender()
|
||||
logging.debug("Clearing signal cache of tab {}".format(self.indexOf(
|
||||
sender)))
|
||||
sender.signal_cache.clear()
|
||||
|
||||
def _signal_needs_caching(self, signal):
|
||||
"""Return True if a signal should be cached, false otherwise."""
|
||||
ignore_signals = ['linkHovered']
|
||||
return not signal_name(signal) in ignore_signals
|
||||
|
||||
|
||||
class BrowserTab(QWebView):
|
||||
|
||||
@ -478,7 +442,7 @@ class BrowserTab(QWebView):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
self.signal_cache = OrderedDict()
|
||||
self.signal_cache = SignalCache(uncached=['linkHovered'])
|
||||
self.loadProgress.connect(self.set_progress)
|
||||
self.page().setLinkDelegationPolicy(QWebPage.DelegateAllLinks)
|
||||
self.page().linkHovered.connect(self.linkHovered)
|
||||
|
Loading…
Reference in New Issue
Block a user