From 8b5daad367080ab2f337dba46c078d97c899e8a5 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 23 Apr 2014 16:57:12 +0200 Subject: [PATCH] Add ModeManager --- qutebrowser/app.py | 21 +----- qutebrowser/browser/hints.py | 15 +--- qutebrowser/utils/modemanager.py | 106 +++++++++++++++++++++++++++ qutebrowser/widgets/tabbedbrowser.py | 4 - 4 files changed, 113 insertions(+), 33 deletions(-) create mode 100644 qutebrowser/utils/modemanager.py diff --git a/qutebrowser/app.py b/qutebrowser/app.py index 694ca8a61..f90e07a06 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -53,6 +53,7 @@ import qutebrowser.config.style as style import qutebrowser.config.config as config import qutebrowser.network.qutescheme as qutescheme import qutebrowser.utils.message as message +import qutebrowser.utils.modemanager as modemanager from qutebrowser.widgets.mainwindow import MainWindow from qutebrowser.widgets.crash import CrashDialog from qutebrowser.commands.keys import CommandKeyParser @@ -83,7 +84,6 @@ class QuteBrowser(QApplication): _timers: List of used QTimers so they don't get GCed. _shutting_down: True if we're currently shutting down. _quit_status: The current quitting status. - _mode: The mode we're currently in. _opened_urls: List of opened URLs. """ @@ -93,7 +93,6 @@ class QuteBrowser(QApplication): self._timers = [] self._opened_urls = [] self._shutting_down = False - self._mode = None sys.excepthook = self._exception_hook @@ -130,10 +129,11 @@ class QuteBrowser(QApplication): } self._init_cmds() self.mainwindow = MainWindow() + modemanager.init(self.mainwindow.tabs.keypress, self._keyparsers, self) self.setQuitOnLastWindowClosed(False) self._connect_signals() - self.set_mode("normal") + modemanager.enter("normal") self.mainwindow.show() self._python_hacks() @@ -246,7 +246,6 @@ class QuteBrowser(QApplication): # misc self.lastWindowClosed.connect(self.shutdown) tabs.quit.connect(self.shutdown) - tabs.set_mode.connect(self.set_mode) tabs.currentChanged.connect(self.mainwindow.update_inspector) # status bar @@ -401,20 +400,6 @@ class QuteBrowser(QApplication): logging.debug("maybe_quit quitting.") self.quit() - @pyqtSlot(str) - def set_mode(self, mode): - """Set a key input mode. - - Args: - mode: The new mode to set, as an index for self._keyparsers. - """ - if self._mode is not None: - oldhandler = self._keyparsers[self._mode] - self.mainwindow.tabs.keypress.disconnect(oldhandler.handle) - handler = self._keyparsers[mode] - self.mainwindow.tabs.keypress.connect(handler.handle) - self._mode = mode - @cmdutils.register(instance='', maxsplit=0) def pyeval(self, s): """Evaluate a python string and display the results as a webpage. diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py index 00cbf8141..c5dde063a 100644 --- a/qutebrowser/browser/hints.py +++ b/qutebrowser/browser/hints.py @@ -28,6 +28,7 @@ from PyQt5.QtWidgets import QApplication import qutebrowser.config.config as config import qutebrowser.utils.message as message import qutebrowser.utils.url as urlutils +import qutebrowser.utils.modemanager as modemanager from qutebrowser.utils.keyparser import KeyParser @@ -104,8 +105,6 @@ class HintManager(QObject): Signals: hint_strings_updated: Emitted when the possible hint strings changed. arg: A list of hint strings. - set_mode: Emitted when the input mode should be changed. - arg: The new mode, as a string. mouse_event: Mouse event to be posted in the web view. arg: A QMouseEvent openurl: Open a new url @@ -146,7 +145,6 @@ class HintManager(QObject): """ hint_strings_updated = pyqtSignal(list) - set_mode = pyqtSignal(str) mouse_event = pyqtSignal('QMouseEvent') set_open_target = pyqtSignal(str) set_cmd_text = pyqtSignal(str) @@ -353,7 +351,6 @@ class HintManager(QObject): Emit: hint_strings_updated: Emitted to update keypraser. - set_mode: Emitted to enter hinting mode """ self._target = target self._baseurl = baseurl @@ -395,14 +392,10 @@ class HintManager(QObject): self._elems[string] = ElemTuple(e, label) frame.contentsSizeChanged.connect(self.on_contents_size_changed) self.hint_strings_updated.emit(strings) - self.set_mode.emit("hint") + modemanager.enter("hint") def stop(self): - """Stop hinting. - - Emit: - set_mode: Emitted to leave hinting mode. - """ + """Stop hinting.""" for elem in self._elems.values(): elem.label.removeFromDocument() self._frame.contentsSizeChanged.disconnect( @@ -410,7 +403,7 @@ class HintManager(QObject): self._elems = {} self._target = None self._frame = None - self.set_mode.emit("normal") + modemanager.enter("normal") message.clear() def handle_partial_key(self, keystr): diff --git a/qutebrowser/utils/modemanager.py b/qutebrowser/utils/modemanager.py new file mode 100644 index 000000000..11c34451a --- /dev/null +++ b/qutebrowser/utils/modemanager.py @@ -0,0 +1,106 @@ +# Copyright 2014 Florian Bruhin (The Compiler) +# +# 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 . + +"""Mode manager singleton which handles the current keyboard mode. + +Module attributes: + manager: The ModeManager instance. +""" + +import logging + +from PyQt5.QtCore import QObject + + +manager = None + + +def init(source, parsers=None, parent=None): + """Initialize the global ModeManager. + + This needs to be done by hand because the import time is before Qt is ready + for everything. + + Args: + source: The keypress source signal. + parsers: A dict of KeyParsers to register. + parent: Parent to use for ModeManager. + """ + global manager + manager = ModeManager(source, parsers, parent) + + +def enter(mode): + """Enter the mode 'mode'.""" + manager.enter(mode) + + +def register(mode, handler): + """Register a new mode. + + Args: + mode: The name of the mode. + handler: Handler for keyPressEvents. + """ + manager.register(mode, handler) + + +class ModeManager(QObject): + + """Manager for keyboard modes. + + Attributes: + _source: The keypress source signal. + _handlers: A dictionary of modes and their handlers. + mode: The current mode. + """ + + def __init__(self, sourcesig, parsers=None, parent=None): + """Constructor. + + Args: + sourcesig: The signal which gets emitted on a keypress. + parsers: A list of parsers to register. + """ + super().__init__(parent) + self._source = sourcesig + self._handlers = {} + self.mode = None + if parsers is not None: + for name, parser in parsers.items(): + self._handlers[name] = parser.handle + + def register(self, mode, handler): + """Register a new mode. + + Args: + mode: The name of the mode. + handler: Handler for keyPressEvents. + """ + self._handlers[mode] = handler + + def enter(self, mode): + """Enter a new mode.""" + oldmode = self.mode + logging.debug("Switching mode: {} -> {}".format(oldmode, mode)) + if oldmode is not None: + try: + self._source.disconnect(self._handlers[oldmode]) + except TypeError: + logging.debug("Could not disconnect mode {}".format(oldmode)) + self._source.connect(self._handlers[mode]) + self.mode = mode diff --git a/qutebrowser/widgets/tabbedbrowser.py b/qutebrowser/widgets/tabbedbrowser.py index ddd5460c4..7e334e630 100644 --- a/qutebrowser/widgets/tabbedbrowser.py +++ b/qutebrowser/widgets/tabbedbrowser.py @@ -69,8 +69,6 @@ class TabbedBrowser(TabWidget): arg 2: y-position in %. hint_strings_updated: Hint strings were updated. arg: A list of hint strings. - set_mode: The input mode should be changed. - arg: The new mode as a string. keypress: A key was pressed. arg: The QKeyEvent leading to the keypress. shutdown_complete: The shuttdown is completed. @@ -89,7 +87,6 @@ class TabbedBrowser(TabWidget): cur_scroll_perc_changed = pyqtSignal(int, int) hint_strings_updated = pyqtSignal(list) set_cmd_text = pyqtSignal(str) - set_mode = pyqtSignal(str) keypress = pyqtSignal('QKeyEvent') shutdown_complete = pyqtSignal() quit = pyqtSignal() @@ -143,7 +140,6 @@ class TabbedBrowser(TabWidget): tab.urlChanged.connect(self._filter.create(self.cur_url_changed)) # hintmanager tab.hintmanager.hint_strings_updated.connect(self.hint_strings_updated) - tab.hintmanager.set_mode.connect(self.set_mode) tab.hintmanager.set_cmd_text.connect(self.set_cmd_text) # misc tab.titleChanged.connect(self.on_title_changed)