Clean up imports
This commit is contained in:
parent
45608ee9f8
commit
d625cde28c
@ -289,7 +289,7 @@ or
|
|||||||
|
|
||||||
[source,python]
|
[source,python]
|
||||||
----
|
----
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.utils import log
|
||||||
...
|
...
|
||||||
log.foo.debug("Hello World")
|
log.foo.debug("Hello World")
|
||||||
----
|
----
|
||||||
|
@ -20,9 +20,10 @@
|
|||||||
|
|
||||||
"""Entry point for qutebrowser. Simply execute qutebrowser."""
|
"""Entry point for qutebrowser. Simply execute qutebrowser."""
|
||||||
|
|
||||||
import qutebrowser.qutebrowser
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import qutebrowser.qutebrowser
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(qutebrowser.qutebrowser.main())
|
sys.exit(qutebrowser.qutebrowser.main())
|
||||||
|
@ -26,46 +26,28 @@ import faulthandler
|
|||||||
import configparser
|
import configparser
|
||||||
import signal
|
import signal
|
||||||
import warnings
|
import warnings
|
||||||
from bdb import BdbQuit
|
import bdb
|
||||||
from base64 import b64encode
|
import base64
|
||||||
from functools import partial
|
import functools
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
|
from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
|
||||||
from PyQt5.QtCore import (pyqtSlot, QTimer, QEventLoop, Qt, QStandardPaths,
|
from PyQt5.QtCore import (pyqtSlot, QTimer, QEventLoop, Qt, QStandardPaths,
|
||||||
qInstallMessageHandler, QObject, QUrl)
|
qInstallMessageHandler, QObject, QUrl)
|
||||||
|
|
||||||
import qutebrowser
|
import qutebrowser
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import userscripts, runners
|
||||||
import qutebrowser.config.style as style
|
from qutebrowser.commands import utils as cmdutils
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import (style, config, websettings, iniparsers,
|
||||||
import qutebrowser.network.qutescheme as qutescheme
|
lineparser, conftypes)
|
||||||
import qutebrowser.config.websettings as websettings
|
from qutebrowser.network import qutescheme, proxy
|
||||||
import qutebrowser.network.proxy as proxy
|
from qutebrowser.browser import quickmarks, cookies, downloads
|
||||||
import qutebrowser.browser.quickmarks as quickmarks
|
from qutebrowser.widgets import mainwindow, console, crash
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.keyinput import modeparsers, keyparser, modeman
|
||||||
import qutebrowser.utils.version as version
|
from qutebrowser.utils import log, version, message, utilcmds, readline
|
||||||
import qutebrowser.utils.url as urlutils
|
from qutebrowser.utils import url as urlutils
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.utils import misc as utils
|
||||||
import qutebrowser.commands.userscripts as userscripts
|
from qutebrowser.utils import qt as qtutils
|
||||||
import qutebrowser.utils.utilcmds as utilcmds
|
from qutebrowser.utils import usertypes as utypes
|
||||||
from qutebrowser.config.config import ConfigManager
|
|
||||||
from qutebrowser.keyinput.modeman import ModeManager
|
|
||||||
from qutebrowser.widgets.mainwindow import MainWindow
|
|
||||||
from qutebrowser.widgets.console import ConsoleWidget
|
|
||||||
from qutebrowser.widgets.crash import (ExceptionCrashDialog, FatalCrashDialog,
|
|
||||||
ReportDialog)
|
|
||||||
from qutebrowser.keyinput.modeparsers import (NormalKeyParser, HintKeyParser,
|
|
||||||
PromptKeyParser)
|
|
||||||
from qutebrowser.keyinput.keyparser import PassthroughKeyParser
|
|
||||||
from qutebrowser.commands.runners import CommandRunner, SearchRunner
|
|
||||||
from qutebrowser.config.iniparsers import ReadWriteConfigParser
|
|
||||||
from qutebrowser.config.lineparser import LineConfigParser
|
|
||||||
from qutebrowser.browser.cookies import CookieJar
|
|
||||||
from qutebrowser.browser.downloads import DownloadManager
|
|
||||||
from qutebrowser.utils.misc import get_standard_dir, actute_warning
|
|
||||||
from qutebrowser.utils.qt import get_qt_args
|
|
||||||
from qutebrowser.utils.readline import ReadlineBridge
|
|
||||||
from qutebrowser.utils.usertypes import Timer, KeyMode
|
|
||||||
|
|
||||||
|
|
||||||
class Application(QApplication):
|
class Application(QApplication):
|
||||||
@ -104,9 +86,9 @@ class Application(QApplication):
|
|||||||
# We don't enable this earlier because some imports trigger
|
# We don't enable this earlier because some imports trigger
|
||||||
# warnings (which are not our fault).
|
# warnings (which are not our fault).
|
||||||
warnings.simplefilter('default')
|
warnings.simplefilter('default')
|
||||||
qt_args = get_qt_args(args)
|
qt_args = qtutils.get_qt_args(args)
|
||||||
log.init.debug("Qt arguments: {}, based on {}".format(qt_args, args))
|
log.init.debug("Qt arguments: {}, based on {}".format(qt_args, args))
|
||||||
super().__init__(get_qt_args(args))
|
super().__init__(qt_args)
|
||||||
self._quit_status = {
|
self._quit_status = {
|
||||||
'crash': True,
|
'crash': True,
|
||||||
'tabs': False,
|
'tabs': False,
|
||||||
@ -129,7 +111,7 @@ class Application(QApplication):
|
|||||||
self.args = args
|
self.args = args
|
||||||
log.init.debug("Starting init...")
|
log.init.debug("Starting init...")
|
||||||
self._init_misc()
|
self._init_misc()
|
||||||
actute_warning()
|
utils.actute_warning()
|
||||||
log.init.debug("Initializing config...")
|
log.init.debug("Initializing config...")
|
||||||
self._init_config()
|
self._init_config()
|
||||||
log.init.debug("Initializing crashlog...")
|
log.init.debug("Initializing crashlog...")
|
||||||
@ -147,25 +129,25 @@ class Application(QApplication):
|
|||||||
log.init.debug("Initializing utility commands...")
|
log.init.debug("Initializing utility commands...")
|
||||||
utilcmds.init()
|
utilcmds.init()
|
||||||
log.init.debug("Initializing cookies...")
|
log.init.debug("Initializing cookies...")
|
||||||
self.cookiejar = CookieJar(self)
|
self.cookiejar = cookies.CookieJar(self)
|
||||||
log.init.debug("Initializing commands...")
|
log.init.debug("Initializing commands...")
|
||||||
self.commandrunner = CommandRunner()
|
self.commandrunner = runners.CommandRunner()
|
||||||
log.init.debug("Initializing search...")
|
log.init.debug("Initializing search...")
|
||||||
self.searchrunner = SearchRunner(self)
|
self.searchrunner = runners.SearchRunner(self)
|
||||||
log.init.debug("Initializing downloads...")
|
log.init.debug("Initializing downloads...")
|
||||||
self.downloadmanager = DownloadManager(self)
|
self.downloadmanager = downloads.DownloadManager(self)
|
||||||
log.init.debug("Initializing main window...")
|
log.init.debug("Initializing main window...")
|
||||||
self.mainwindow = MainWindow()
|
self.mainwindow = mainwindow.MainWindow()
|
||||||
self.modeman.mainwindow = self.mainwindow
|
self.modeman.mainwindow = self.mainwindow
|
||||||
log.init.debug("Initializing debug console...")
|
log.init.debug("Initializing debug console...")
|
||||||
self.debugconsole = ConsoleWidget()
|
self.debugconsole = console.ConsoleWidget()
|
||||||
log.init.debug("Initializing eventfilter...")
|
log.init.debug("Initializing eventfilter...")
|
||||||
self.installEventFilter(self.modeman)
|
self.installEventFilter(self.modeman)
|
||||||
self.setQuitOnLastWindowClosed(False)
|
self.setQuitOnLastWindowClosed(False)
|
||||||
|
|
||||||
log.init.debug("Connecting signals...")
|
log.init.debug("Connecting signals...")
|
||||||
self._connect_signals()
|
self._connect_signals()
|
||||||
self.modeman.enter(KeyMode.normal, 'init')
|
self.modeman.enter(utypes.KeyMode.normal, 'init')
|
||||||
|
|
||||||
log.init.debug("Showing mainwindow...")
|
log.init.debug("Showing mainwindow...")
|
||||||
if not args.nowindow:
|
if not args.nowindow:
|
||||||
@ -183,14 +165,15 @@ class Application(QApplication):
|
|||||||
def _init_config(self):
|
def _init_config(self):
|
||||||
"""Inizialize and read the config."""
|
"""Inizialize and read the config."""
|
||||||
if self.args.confdir is None:
|
if self.args.confdir is None:
|
||||||
confdir = get_standard_dir(QStandardPaths.ConfigLocation)
|
confdir = utils.get_standard_dir(QStandardPaths.ConfigLocation)
|
||||||
elif self.args.confdir == '':
|
elif self.args.confdir == '':
|
||||||
confdir = None
|
confdir = None
|
||||||
else:
|
else:
|
||||||
confdir = self.args.confdir
|
confdir = self.args.confdir
|
||||||
try:
|
try:
|
||||||
self.config = ConfigManager(confdir, 'qutebrowser.conf', self)
|
self.config = config.ConfigManager(confdir, 'qutebrowser.conf',
|
||||||
except (config.ValidationError,
|
self)
|
||||||
|
except (conftypes.ValidationError,
|
||||||
config.NoOptionError,
|
config.NoOptionError,
|
||||||
config.InterpolationSyntaxError,
|
config.InterpolationSyntaxError,
|
||||||
configparser.InterpolationError,
|
configparser.InterpolationError,
|
||||||
@ -207,47 +190,49 @@ class Application(QApplication):
|
|||||||
msgbox.exec_()
|
msgbox.exec_()
|
||||||
# We didn't really initialize much so far, so we just quit hard.
|
# We didn't really initialize much so far, so we just quit hard.
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
self.stateconfig = ReadWriteConfigParser(confdir, 'state')
|
self.stateconfig = iniparsers.ReadWriteConfigParser(confdir, 'state')
|
||||||
self.cmd_history = LineConfigParser(confdir, 'cmd_history',
|
self.cmd_history = lineparser.LineConfigParser(
|
||||||
('completion', 'history-length'))
|
confdir, 'cmd_history', ('completion', 'history-length'))
|
||||||
|
|
||||||
def _init_modes(self):
|
def _init_modes(self):
|
||||||
"""Inizialize the mode manager and the keyparsers."""
|
"""Inizialize the mode manager and the keyparsers."""
|
||||||
self._keyparsers = {
|
self._keyparsers = {
|
||||||
KeyMode.normal:
|
utypes.KeyMode.normal:
|
||||||
NormalKeyParser(self),
|
modeparsers.NormalKeyParser(self),
|
||||||
KeyMode.hint:
|
utypes.KeyMode.hint:
|
||||||
HintKeyParser(self),
|
modeparsers.HintKeyParser(self),
|
||||||
KeyMode.insert:
|
utypes.KeyMode.insert:
|
||||||
PassthroughKeyParser('keybind.insert', self),
|
keyparser.PassthroughKeyParser('keybind.insert', self),
|
||||||
KeyMode.passthrough:
|
utypes.KeyMode.passthrough:
|
||||||
PassthroughKeyParser('keybind.passthrough', self),
|
keyparser.PassthroughKeyParser('keybind.passthrough', self),
|
||||||
KeyMode.command:
|
utypes.KeyMode.command:
|
||||||
PassthroughKeyParser('keybind.command', self),
|
keyparser.PassthroughKeyParser('keybind.command', self),
|
||||||
KeyMode.prompt:
|
utypes.KeyMode.prompt:
|
||||||
PassthroughKeyParser('keybind.prompt', self, warn=False),
|
keyparser.PassthroughKeyParser('keybind.prompt', self,
|
||||||
KeyMode.yesno:
|
warn=False),
|
||||||
PromptKeyParser(self),
|
utypes.KeyMode.yesno:
|
||||||
|
modeparsers.PromptKeyParser(self),
|
||||||
}
|
}
|
||||||
self.modeman = ModeManager(self)
|
self.modeman = modeman.ModeManager(self)
|
||||||
self.modeman.register(KeyMode.normal,
|
self.modeman.register(utypes.KeyMode.normal,
|
||||||
self._keyparsers[KeyMode.normal].handle)
|
self._keyparsers[utypes.KeyMode.normal].handle)
|
||||||
self.modeman.register(KeyMode.hint,
|
self.modeman.register(utypes.KeyMode.hint,
|
||||||
self._keyparsers[KeyMode.hint].handle)
|
self._keyparsers[utypes.KeyMode.hint].handle)
|
||||||
self.modeman.register(KeyMode.insert,
|
self.modeman.register(utypes.KeyMode.insert,
|
||||||
self._keyparsers[KeyMode.insert].handle,
|
self._keyparsers[utypes.KeyMode.insert].handle,
|
||||||
passthrough=True)
|
passthrough=True)
|
||||||
self.modeman.register(KeyMode.passthrough,
|
self.modeman.register(
|
||||||
self._keyparsers[KeyMode.passthrough].handle,
|
utypes.KeyMode.passthrough,
|
||||||
|
self._keyparsers[utypes.KeyMode.passthrough].handle,
|
||||||
|
passthrough=True)
|
||||||
|
self.modeman.register(utypes.KeyMode.command,
|
||||||
|
self._keyparsers[utypes.KeyMode.command].handle,
|
||||||
passthrough=True)
|
passthrough=True)
|
||||||
self.modeman.register(KeyMode.command,
|
self.modeman.register(utypes.KeyMode.prompt,
|
||||||
self._keyparsers[KeyMode.command].handle,
|
self._keyparsers[utypes.KeyMode.prompt].handle,
|
||||||
passthrough=True)
|
passthrough=True)
|
||||||
self.modeman.register(KeyMode.prompt,
|
self.modeman.register(utypes.KeyMode.yesno,
|
||||||
self._keyparsers[KeyMode.prompt].handle,
|
self._keyparsers[utypes.KeyMode.yesno].handle)
|
||||||
passthrough=True)
|
|
||||||
self.modeman.register(KeyMode.yesno,
|
|
||||||
self._keyparsers[KeyMode.yesno].handle)
|
|
||||||
|
|
||||||
def _init_misc(self):
|
def _init_misc(self):
|
||||||
"""Initialize misc things."""
|
"""Initialize misc things."""
|
||||||
@ -263,7 +248,7 @@ class Application(QApplication):
|
|||||||
self.setApplicationName("qutebrowser")
|
self.setApplicationName("qutebrowser")
|
||||||
self.setApplicationVersion(qutebrowser.__version__)
|
self.setApplicationVersion(qutebrowser.__version__)
|
||||||
self.messagebridge = message.MessageBridge(self)
|
self.messagebridge = message.MessageBridge(self)
|
||||||
self.rl_bridge = ReadlineBridge()
|
self.rl_bridge = readline.ReadlineBridge()
|
||||||
|
|
||||||
def _handle_segfault(self):
|
def _handle_segfault(self):
|
||||||
"""Handle a segfault from a previous run."""
|
"""Handle a segfault from a previous run."""
|
||||||
@ -272,8 +257,8 @@ class Application(QApplication):
|
|||||||
# However this also means if the logfile is there for some weird
|
# However this also means if the logfile is there for some weird
|
||||||
# reason, we'll *always* log to stderr, but that's still better than no
|
# reason, we'll *always* log to stderr, but that's still better than no
|
||||||
# dialogs at all.
|
# dialogs at all.
|
||||||
logname = os.path.join(get_standard_dir(QStandardPaths.DataLocation),
|
path = utils.get_standard_dir(QStandardPaths.DataLocation)
|
||||||
'crash.log')
|
logname = os.path.join(path, 'crash.log')
|
||||||
# First check if an old logfile exists.
|
# First check if an old logfile exists.
|
||||||
if os.path.exists(logname):
|
if os.path.exists(logname):
|
||||||
with open(logname, 'r', encoding='ascii') as f:
|
with open(logname, 'r', encoding='ascii') as f:
|
||||||
@ -287,7 +272,7 @@ class Application(QApplication):
|
|||||||
log.init.warning("Could not remove crash log!")
|
log.init.warning("Could not remove crash log!")
|
||||||
else:
|
else:
|
||||||
self._init_crashlogfile()
|
self._init_crashlogfile()
|
||||||
self._crashdlg = FatalCrashDialog(data)
|
self._crashdlg = crash.FatalCrashDialog(data)
|
||||||
self._crashdlg.show()
|
self._crashdlg.show()
|
||||||
else:
|
else:
|
||||||
# Crashlog exists but without data.
|
# Crashlog exists but without data.
|
||||||
@ -307,8 +292,8 @@ class Application(QApplication):
|
|||||||
|
|
||||||
def _init_crashlogfile(self):
|
def _init_crashlogfile(self):
|
||||||
"""Start a new logfile and redirect faulthandler to it."""
|
"""Start a new logfile and redirect faulthandler to it."""
|
||||||
logname = os.path.join(get_standard_dir(QStandardPaths.DataLocation),
|
path = utils.get_standard_dir(QStandardPaths.DataLocation)
|
||||||
'crash.log')
|
logname = os.path.join(path, 'crash.log')
|
||||||
self._crashlogfile = open(logname, 'w', encoding='ascii')
|
self._crashlogfile = open(logname, 'w', encoding='ascii')
|
||||||
faulthandler.enable(self._crashlogfile)
|
faulthandler.enable(self._crashlogfile)
|
||||||
if (hasattr(faulthandler, 'register') and
|
if (hasattr(faulthandler, 'register') and
|
||||||
@ -360,7 +345,7 @@ class Application(QApplication):
|
|||||||
"""
|
"""
|
||||||
signal.signal(signal.SIGINT, self.interrupt)
|
signal.signal(signal.SIGINT, self.interrupt)
|
||||||
signal.signal(signal.SIGTERM, self.interrupt)
|
signal.signal(signal.SIGTERM, self.interrupt)
|
||||||
timer = Timer(self, 'python_hacks')
|
timer = utypes.Timer(self, 'python_hacks')
|
||||||
timer.start(500)
|
timer.start(500)
|
||||||
timer.timeout.connect(lambda: None)
|
timer.timeout.connect(lambda: None)
|
||||||
self._timers.append(timer)
|
self._timers.append(timer)
|
||||||
@ -392,15 +377,16 @@ class Application(QApplication):
|
|||||||
cmd.got_search_rev.connect(self.searchrunner.search_rev)
|
cmd.got_search_rev.connect(self.searchrunner.search_rev)
|
||||||
cmd.returnPressed.connect(tabs.setFocus)
|
cmd.returnPressed.connect(tabs.setFocus)
|
||||||
self.searchrunner.do_search.connect(tabs.search)
|
self.searchrunner.do_search.connect(tabs.search)
|
||||||
kp[KeyMode.normal].keystring_updated.connect(status.keystring.setText)
|
kp[utypes.KeyMode.normal].keystring_updated.connect(
|
||||||
|
status.keystring.setText)
|
||||||
tabs.got_cmd.connect(self.commandrunner.run_safely)
|
tabs.got_cmd.connect(self.commandrunner.run_safely)
|
||||||
|
|
||||||
# hints
|
# hints
|
||||||
kp[KeyMode.hint].fire_hint.connect(tabs.fire_hint)
|
kp[utypes.KeyMode.hint].fire_hint.connect(tabs.fire_hint)
|
||||||
kp[KeyMode.hint].filter_hints.connect(tabs.filter_hints)
|
kp[utypes.KeyMode.hint].filter_hints.connect(tabs.filter_hints)
|
||||||
kp[KeyMode.hint].keystring_updated.connect(tabs.handle_hint_key)
|
kp[utypes.KeyMode.hint].keystring_updated.connect(tabs.handle_hint_key)
|
||||||
tabs.hint_strings_updated.connect(
|
tabs.hint_strings_updated.connect(
|
||||||
kp[KeyMode.hint].on_hint_strings_updated)
|
kp[utypes.KeyMode.hint].on_hint_strings_updated)
|
||||||
|
|
||||||
# messages
|
# messages
|
||||||
self.messagebridge.s_error.connect(status.disp_error)
|
self.messagebridge.s_error.connect(status.disp_error)
|
||||||
@ -413,8 +399,8 @@ class Application(QApplication):
|
|||||||
# config
|
# config
|
||||||
self.config.style_changed.connect(style.invalidate_caches)
|
self.config.style_changed.connect(style.invalidate_caches)
|
||||||
for obj in (tabs, completion, self.mainwindow, self.cmd_history,
|
for obj in (tabs, completion, self.mainwindow, self.cmd_history,
|
||||||
websettings, kp[KeyMode.normal], self.modeman, status,
|
websettings, kp[utypes.KeyMode.normal], self.modeman,
|
||||||
status.txt):
|
status, status.txt):
|
||||||
self.config.changed.connect(obj.on_config_changed)
|
self.config.changed.connect(obj.on_config_changed)
|
||||||
|
|
||||||
# statusbar
|
# statusbar
|
||||||
@ -498,7 +484,8 @@ class Application(QApplication):
|
|||||||
|
|
||||||
def _save_geometry(self):
|
def _save_geometry(self):
|
||||||
"""Save the window geometry to the state config."""
|
"""Save the window geometry to the state config."""
|
||||||
geom = b64encode(bytes(self.mainwindow.saveGeometry())).decode('ASCII')
|
data = bytes(self.mainwindow.saveGeometry())
|
||||||
|
geom = base64.b64encode(data).decode('ASCII')
|
||||||
try:
|
try:
|
||||||
self.stateconfig.add_section('geometry')
|
self.stateconfig.add_section('geometry')
|
||||||
except configparser.DuplicateSectionError:
|
except configparser.DuplicateSectionError:
|
||||||
@ -530,7 +517,7 @@ class Application(QApplication):
|
|||||||
"""
|
"""
|
||||||
# pylint: disable=broad-except
|
# pylint: disable=broad-except
|
||||||
|
|
||||||
if exctype is BdbQuit or not issubclass(exctype, Exception):
|
if exctype is bdb.BdbQuit or not issubclass(exctype, Exception):
|
||||||
# pdb exit, KeyboardInterrupt, ...
|
# pdb exit, KeyboardInterrupt, ...
|
||||||
try:
|
try:
|
||||||
self.shutdown()
|
self.shutdown()
|
||||||
@ -580,8 +567,8 @@ class Application(QApplication):
|
|||||||
log.destroy.debug("Error while preventing shutdown: {}: {}".format(
|
log.destroy.debug("Error while preventing shutdown: {}: {}".format(
|
||||||
e.__class__.__name__, e))
|
e.__class__.__name__, e))
|
||||||
QApplication.closeAllWindows()
|
QApplication.closeAllWindows()
|
||||||
self._crashdlg = ExceptionCrashDialog(pages, history, exc, widgets,
|
self._crashdlg = crash.ExceptionCrashDialog(pages, history, exc,
|
||||||
objects)
|
widgets, objects)
|
||||||
ret = self._crashdlg.exec_()
|
ret = self._crashdlg.exec_()
|
||||||
if ret == QDialog.Accepted: # restore
|
if ret == QDialog.Accepted: # restore
|
||||||
self.restart(shutdown=False, pages=pages)
|
self.restart(shutdown=False, pages=pages)
|
||||||
@ -655,7 +642,7 @@ class Application(QApplication):
|
|||||||
history = self.mainwindow.status.cmd.history[-5:]
|
history = self.mainwindow.status.cmd.history[-5:]
|
||||||
widgets = self.get_all_widgets()
|
widgets = self.get_all_widgets()
|
||||||
objects = self.get_all_objects()
|
objects = self.get_all_objects()
|
||||||
self._crashdlg = ReportDialog(pages, history, widgets, objects)
|
self._crashdlg = crash.ReportDialog(pages, history, widgets, objects)
|
||||||
self._crashdlg.show()
|
self._crashdlg.show()
|
||||||
|
|
||||||
@cmdutils.register(instance='', debug=True, name='debug-console')
|
@cmdutils.register(instance='', debug=True, name='debug-console')
|
||||||
@ -674,7 +661,7 @@ class Application(QApplication):
|
|||||||
signal.signal(signal.SIGINT, self.interrupt_forcefully)
|
signal.signal(signal.SIGINT, self.interrupt_forcefully)
|
||||||
signal.signal(signal.SIGTERM, self.interrupt_forcefully)
|
signal.signal(signal.SIGTERM, self.interrupt_forcefully)
|
||||||
# If we call shutdown directly here, we get a segfault.
|
# If we call shutdown directly here, we get a segfault.
|
||||||
QTimer.singleShot(0, partial(self.shutdown, 128 + signum))
|
QTimer.singleShot(0, functools.partial(self.shutdown, 128 + signum))
|
||||||
|
|
||||||
def interrupt_forcefully(self, signum, _frame):
|
def interrupt_forcefully(self, signum, _frame):
|
||||||
"""Interrupt forcefully on the second SIGINT/SIGTERM request.
|
"""Interrupt forcefully on the second SIGINT/SIGTERM request.
|
||||||
@ -689,7 +676,7 @@ class Application(QApplication):
|
|||||||
signal.signal(signal.SIGTERM, self.interrupt_really_forcefully)
|
signal.signal(signal.SIGTERM, self.interrupt_really_forcefully)
|
||||||
# This *should* work without a QTimer, but because of the trouble in
|
# This *should* work without a QTimer, but because of the trouble in
|
||||||
# self.interrupt we're better safe than sorry.
|
# self.interrupt we're better safe than sorry.
|
||||||
QTimer.singleShot(0, partial(self.exit, 128 + signum))
|
QTimer.singleShot(0, functools.partial(self.exit, 128 + signum))
|
||||||
|
|
||||||
def interrupt_really_forcefully(self, signum, _frame):
|
def interrupt_really_forcefully(self, signum, _frame):
|
||||||
"""Interrupt with even more force on the third SIGINT/SIGTERM request.
|
"""Interrupt with even more force on the third SIGINT/SIGTERM request.
|
||||||
@ -722,7 +709,7 @@ class Application(QApplication):
|
|||||||
# in the real main event loop, or we'll get a segfault.
|
# in the real main event loop, or we'll get a segfault.
|
||||||
log.destroy.debug("Deferring real shutdown because question was "
|
log.destroy.debug("Deferring real shutdown because question was "
|
||||||
"active.")
|
"active.")
|
||||||
QTimer.singleShot(0, partial(self._shutdown, status))
|
QTimer.singleShot(0, functools.partial(self._shutdown, status))
|
||||||
else:
|
else:
|
||||||
# If we have no questions to shut down, we are already in the real
|
# If we have no questions to shut down, we are already in the real
|
||||||
# event loop, so we can shut down immediately.
|
# event loop, so we can shut down immediately.
|
||||||
@ -773,7 +760,7 @@ class Application(QApplication):
|
|||||||
log.destroy.debug("Deferring QApplication::exit...")
|
log.destroy.debug("Deferring QApplication::exit...")
|
||||||
# We use a singleshot timer to exit here to minimize the likelyhood of
|
# We use a singleshot timer to exit here to minimize the likelyhood of
|
||||||
# segfaults.
|
# segfaults.
|
||||||
QTimer.singleShot(0, partial(self.exit, status))
|
QTimer.singleShot(0, functools.partial(self.exit, status))
|
||||||
|
|
||||||
def exit(self, status):
|
def exit(self, status):
|
||||||
"""Extend QApplication::exit to log the event."""
|
"""Extend QApplication::exit to log the event."""
|
||||||
|
@ -29,19 +29,14 @@ from PyQt5.QtGui import QClipboard
|
|||||||
from PyQt5.QtPrintSupport import QPrintDialog, QPrintPreviewDialog
|
from PyQt5.QtPrintSupport import QPrintDialog, QPrintPreviewDialog
|
||||||
from PyQt5.QtWebKitWidgets import QWebInspector
|
from PyQt5.QtWebKitWidgets import QWebInspector
|
||||||
|
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import userscripts
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.commands import utils as cmdutils
|
||||||
import qutebrowser.browser.hints as hints
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.config import config
|
||||||
import qutebrowser.utils.webelem as webelem
|
from qutebrowser.browser import hints, quickmarks
|
||||||
import qutebrowser.browser.quickmarks as quickmarks
|
from qutebrowser.utils import message, webelem, editor, usertypes, log
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.utils import qt as qtutils
|
||||||
import qutebrowser.utils.url as urlutils
|
from qutebrowser.utils import url as urlutils
|
||||||
import qutebrowser.commands.userscripts as userscripts
|
|
||||||
from qutebrowser.utils.qt import check_overflow, check_print_compat
|
|
||||||
from qutebrowser.utils.editor import ExternalEditor
|
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
|
||||||
from qutebrowser.utils.usertypes import KeyMode
|
|
||||||
|
|
||||||
|
|
||||||
class CommandDispatcher:
|
class CommandDispatcher:
|
||||||
@ -82,7 +77,7 @@ class CommandDispatcher:
|
|||||||
perc = int(count)
|
perc = int(count)
|
||||||
else:
|
else:
|
||||||
perc = float(perc)
|
perc = float(perc)
|
||||||
perc = check_overflow(perc, 'int', fatal=False)
|
perc = qtutils.check_overflow(perc, 'int', fatal=False)
|
||||||
frame = self._tabs.currentWidget().page().currentFrame()
|
frame = self._tabs.currentWidget().page().currentFrame()
|
||||||
m = frame.scrollBarMaximum(orientation)
|
m = frame.scrollBarMaximum(orientation)
|
||||||
if m == 0:
|
if m == 0:
|
||||||
@ -94,7 +89,7 @@ class CommandDispatcher:
|
|||||||
widget = self._tabs.currentWidget()
|
widget = self._tabs.currentWidget()
|
||||||
frame = widget.page().currentFrame()
|
frame = widget.page().currentFrame()
|
||||||
if frame is None:
|
if frame is None:
|
||||||
raise CommandError("No frame focused!")
|
raise cmdexc.CommandError("No frame focused!")
|
||||||
widget.hintmanager.follow_prevnext(frame, self._tabs.current_url(),
|
widget.hintmanager.follow_prevnext(frame, self._tabs.current_url(),
|
||||||
prev, newtab)
|
prev, newtab)
|
||||||
|
|
||||||
@ -130,10 +125,10 @@ class CommandDispatcher:
|
|||||||
def _tab_focus_last(self):
|
def _tab_focus_last(self):
|
||||||
"""Select the tab which was last focused."""
|
"""Select the tab which was last focused."""
|
||||||
if self._tabs.last_focused is None:
|
if self._tabs.last_focused is None:
|
||||||
raise CommandError("No last focused tab!")
|
raise cmdexc.CommandError("No last focused tab!")
|
||||||
idx = self._tabs.indexOf(self._tabs.last_focused)
|
idx = self._tabs.indexOf(self._tabs.last_focused)
|
||||||
if idx == -1:
|
if idx == -1:
|
||||||
raise CommandError("Last focused tab vanished!")
|
raise cmdexc.CommandError("Last focused tab vanished!")
|
||||||
self._tabs.setCurrentIndex(idx)
|
self._tabs.setCurrentIndex(idx)
|
||||||
|
|
||||||
def _editor_cleanup(self, oshandle, filename):
|
def _editor_cleanup(self, oshandle, filename):
|
||||||
@ -142,7 +137,7 @@ class CommandDispatcher:
|
|||||||
try:
|
try:
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
raise CommandError("Failed to delete tempfile...")
|
raise cmdexc.CommandError("Failed to delete tempfile...")
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.tabs.cmd')
|
@cmdutils.register(instance='mainwindow.tabs.cmd')
|
||||||
def tab_close(self, count=None):
|
def tab_close(self, count=None):
|
||||||
@ -173,7 +168,7 @@ class CommandDispatcher:
|
|||||||
try:
|
try:
|
||||||
url = urlutils.fuzzy_url(urlstr)
|
url = urlutils.fuzzy_url(urlstr)
|
||||||
except urlutils.FuzzyUrlError as e:
|
except urlutils.FuzzyUrlError as e:
|
||||||
raise CommandError(e)
|
raise cmdexc.CommandError(e)
|
||||||
if tab is None:
|
if tab is None:
|
||||||
if count is None:
|
if count is None:
|
||||||
# We want to open a URL in the current tab, but none exists
|
# We want to open a URL in the current tab, but none exists
|
||||||
@ -214,9 +209,9 @@ class CommandDispatcher:
|
|||||||
Args:
|
Args:
|
||||||
count: The tab index to print, or None.
|
count: The tab index to print, or None.
|
||||||
"""
|
"""
|
||||||
if not check_print_compat():
|
if not qtutils.check_print_compat():
|
||||||
raise CommandError("Printing on Qt < 5.3.0 on Windows is broken, "
|
raise cmdexc.CommandError(
|
||||||
"please upgrade!")
|
"Printing on Qt < 5.3.0 on Windows is broken, please upgrade!")
|
||||||
tab = self._tabs.cntwidget(count)
|
tab = self._tabs.cntwidget(count)
|
||||||
if tab is not None:
|
if tab is not None:
|
||||||
preview = QPrintPreviewDialog()
|
preview = QPrintPreviewDialog()
|
||||||
@ -231,9 +226,9 @@ class CommandDispatcher:
|
|||||||
Args:
|
Args:
|
||||||
count: The tab index to print, or None.
|
count: The tab index to print, or None.
|
||||||
"""
|
"""
|
||||||
if not check_print_compat():
|
if not qtutils.check_print_compat():
|
||||||
raise CommandError("Printing on Qt < 5.3.0 on Windows is broken, "
|
raise cmdexc.CommandError(
|
||||||
"please upgrade!")
|
"Printing on Qt < 5.3.0 on Windows is broken, please upgrade!")
|
||||||
tab = self._tabs.cntwidget(count)
|
tab = self._tabs.cntwidget(count)
|
||||||
if tab is not None:
|
if tab is not None:
|
||||||
printdiag = QPrintDialog()
|
printdiag = QPrintDialog()
|
||||||
@ -303,15 +298,17 @@ class CommandDispatcher:
|
|||||||
widget = self._tabs.currentWidget()
|
widget = self._tabs.currentWidget()
|
||||||
frame = widget.page().mainFrame()
|
frame = widget.page().mainFrame()
|
||||||
if frame is None:
|
if frame is None:
|
||||||
raise CommandError("No frame focused!")
|
raise cmdexc.CommandError("No frame focused!")
|
||||||
try:
|
try:
|
||||||
group_enum = webelem.Group[group.replace('-', '_')]
|
group_enum = webelem.Group[group.replace('-', '_')]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise CommandError("Unknown hinting group {}!".format(group))
|
raise cmdexc.CommandError("Unknown hinting group {}!".format(
|
||||||
|
group))
|
||||||
try:
|
try:
|
||||||
target_enum = hints.Target[target.replace('-', '_')]
|
target_enum = hints.Target[target.replace('-', '_')]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise CommandError("Unknown hinting target {}!".format(target))
|
raise cmdexc.CommandError("Unknown hinting target {}!".format(
|
||||||
|
target))
|
||||||
widget.hintmanager.start(frame, self._tabs.current_url(), group_enum,
|
widget.hintmanager.start(frame, self._tabs.current_url(), group_enum,
|
||||||
target_enum, *args)
|
target_enum, *args)
|
||||||
|
|
||||||
@ -488,7 +485,7 @@ class CommandDispatcher:
|
|||||||
try:
|
try:
|
||||||
level = cmdutils.arg_or_count(zoom, count, default=100)
|
level = cmdutils.arg_or_count(zoom, count, default=100)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise CommandError(e)
|
raise cmdexc.CommandError(e)
|
||||||
tab = self._tabs.currentWidget()
|
tab = self._tabs.currentWidget()
|
||||||
tab.zoom_perc(level)
|
tab.zoom_perc(level)
|
||||||
|
|
||||||
@ -506,7 +503,7 @@ class CommandDispatcher:
|
|||||||
try:
|
try:
|
||||||
url = urlutils.fuzzy_url(urlstr)
|
url = urlutils.fuzzy_url(urlstr)
|
||||||
except urlutils.FuzzyUrlError as e:
|
except urlutils.FuzzyUrlError as e:
|
||||||
raise CommandError(e)
|
raise cmdexc.CommandError(e)
|
||||||
self._tabs.tabopen(url, background=False, explicit=True)
|
self._tabs.tabopen(url, background=False, explicit=True)
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.tabs.cmd', split=False)
|
@cmdutils.register(instance='mainwindow.tabs.cmd', split=False)
|
||||||
@ -515,7 +512,7 @@ class CommandDispatcher:
|
|||||||
try:
|
try:
|
||||||
url = urlutils.fuzzy_url(urlstr)
|
url = urlutils.fuzzy_url(urlstr)
|
||||||
except urlutils.FuzzyUrlError as e:
|
except urlutils.FuzzyUrlError as e:
|
||||||
raise CommandError(e)
|
raise cmdexc.CommandError(e)
|
||||||
self._tabs.tabopen(url, background=True, explicit=True)
|
self._tabs.tabopen(url, background=True, explicit=True)
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.tabs.cmd')
|
@cmdutils.register(instance='mainwindow.tabs.cmd')
|
||||||
@ -524,7 +521,7 @@ class CommandDispatcher:
|
|||||||
if self._tabs.url_stack:
|
if self._tabs.url_stack:
|
||||||
self._tabs.tabopen(self._tabs.url_stack.pop())
|
self._tabs.tabopen(self._tabs.url_stack.pop())
|
||||||
else:
|
else:
|
||||||
raise CommandError("Nothing to undo!")
|
raise cmdexc.CommandError("Nothing to undo!")
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.tabs.cmd')
|
@cmdutils.register(instance='mainwindow.tabs.cmd')
|
||||||
def tab_prev(self, count=1):
|
def tab_prev(self, count=1):
|
||||||
@ -539,7 +536,7 @@ class CommandDispatcher:
|
|||||||
elif config.get('tabs', 'wrap'):
|
elif config.get('tabs', 'wrap'):
|
||||||
self._tabs.setCurrentIndex(newidx % self._tabs.count())
|
self._tabs.setCurrentIndex(newidx % self._tabs.count())
|
||||||
else:
|
else:
|
||||||
raise CommandError("First tab")
|
raise cmdexc.CommandError("First tab")
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.tabs.cmd')
|
@cmdutils.register(instance='mainwindow.tabs.cmd')
|
||||||
def tab_next(self, count=1):
|
def tab_next(self, count=1):
|
||||||
@ -554,7 +551,7 @@ class CommandDispatcher:
|
|||||||
elif config.get('tabs', 'wrap'):
|
elif config.get('tabs', 'wrap'):
|
||||||
self._tabs.setCurrentIndex(newidx % self._tabs.count())
|
self._tabs.setCurrentIndex(newidx % self._tabs.count())
|
||||||
else:
|
else:
|
||||||
raise CommandError("Last tab")
|
raise cmdexc.CommandError("Last tab")
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.tabs.cmd', nargs=(0, 1))
|
@cmdutils.register(instance='mainwindow.tabs.cmd', nargs=(0, 1))
|
||||||
def paste(self, sel=False, tab=False):
|
def paste(self, sel=False, tab=False):
|
||||||
@ -573,12 +570,12 @@ class CommandDispatcher:
|
|||||||
target = "Clipboard"
|
target = "Clipboard"
|
||||||
text = clipboard.text(mode)
|
text = clipboard.text(mode)
|
||||||
if not text:
|
if not text:
|
||||||
raise CommandError("{} is empty.".format(target))
|
raise cmdexc.CommandError("{} is empty.".format(target))
|
||||||
log.misc.debug("{} contained: '{}'".format(target, text))
|
log.misc.debug("{} contained: '{}'".format(target, text))
|
||||||
try:
|
try:
|
||||||
url = urlutils.fuzzy_url(text)
|
url = urlutils.fuzzy_url(text)
|
||||||
except urlutils.FuzzyUrlError as e:
|
except urlutils.FuzzyUrlError as e:
|
||||||
raise CommandError(e)
|
raise cmdexc.CommandError(e)
|
||||||
if tab:
|
if tab:
|
||||||
self._tabs.tabopen(url, explicit=True)
|
self._tabs.tabopen(url, explicit=True)
|
||||||
else:
|
else:
|
||||||
@ -610,12 +607,13 @@ class CommandDispatcher:
|
|||||||
idx = cmdutils.arg_or_count(index, count, default=1,
|
idx = cmdutils.arg_or_count(index, count, default=1,
|
||||||
countzero=self._tabs.count())
|
countzero=self._tabs.count())
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
raise CommandError(e)
|
raise cmdexc.CommandError(e)
|
||||||
cmdutils.check_overflow(idx + 1, 'int')
|
cmdutils.check_overflow(idx + 1, 'int')
|
||||||
if 1 <= idx <= self._tabs.count():
|
if 1 <= idx <= self._tabs.count():
|
||||||
self._tabs.setCurrentIndex(idx - 1)
|
self._tabs.setCurrentIndex(idx - 1)
|
||||||
else:
|
else:
|
||||||
raise CommandError("There's no tab with index {}!".format(idx))
|
raise cmdexc.CommandError("There's no tab with index {}!".format(
|
||||||
|
idx))
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.tabs.cmd')
|
@cmdutils.register(instance='mainwindow.tabs.cmd')
|
||||||
def tab_move(self, direction=None, count=None):
|
def tab_move(self, direction=None, count=None):
|
||||||
@ -632,11 +630,13 @@ class CommandDispatcher:
|
|||||||
try:
|
try:
|
||||||
new_idx = self._tab_move_relative(direction, count)
|
new_idx = self._tab_move_relative(direction, count)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise CommandError("Count must be given for relative moving!")
|
raise cmdexc.CommandError("Count must be given for relative "
|
||||||
|
"moving!")
|
||||||
else:
|
else:
|
||||||
raise CommandError("Invalid direction '{}'!".format(direction))
|
raise cmdexc.CommandError("Invalid direction '{}'!".format(
|
||||||
|
direction))
|
||||||
if not 0 <= new_idx < self._tabs.count():
|
if not 0 <= new_idx < self._tabs.count():
|
||||||
raise CommandError("Can't move tab to position {}!".format(
|
raise cmdexc.CommandError("Can't move tab to position {}!".format(
|
||||||
new_idx))
|
new_idx))
|
||||||
tab = self._tabs.currentWidget()
|
tab = self._tabs.currentWidget()
|
||||||
cur_idx = self._tabs.currentIndex()
|
cur_idx = self._tabs.currentIndex()
|
||||||
@ -697,7 +697,7 @@ class CommandDispatcher:
|
|||||||
urlstr = quickmarks.get(name)
|
urlstr = quickmarks.get(name)
|
||||||
url = QUrl(urlstr)
|
url = QUrl(urlstr)
|
||||||
if not url.isValid():
|
if not url.isValid():
|
||||||
raise CommandError("Invalid URL {} ({})".format(
|
raise cmdexc.CommandError("Invalid URL {} ({})".format(
|
||||||
urlstr, url.errorString()))
|
urlstr, url.errorString()))
|
||||||
self._tabs.currentWidget().openurl(url)
|
self._tabs.currentWidget().openurl(url)
|
||||||
|
|
||||||
@ -719,8 +719,9 @@ class CommandDispatcher:
|
|||||||
cur = self._tabs.currentWidget()
|
cur = self._tabs.currentWidget()
|
||||||
if cur.inspector is None:
|
if cur.inspector is None:
|
||||||
if not config.get('general', 'developer-extras'):
|
if not config.get('general', 'developer-extras'):
|
||||||
raise CommandError("Please enable developer-extras before "
|
raise cmdexc.CommandError(
|
||||||
"using the webinspector!")
|
"Please enable developer-extras before using the "
|
||||||
|
"webinspector!")
|
||||||
cur.inspector = QWebInspector()
|
cur.inspector = QWebInspector()
|
||||||
cur.inspector.setPage(cur.page())
|
cur.inspector.setPage(cur.page())
|
||||||
cur.inspector.show()
|
cur.inspector.show()
|
||||||
@ -728,8 +729,9 @@ class CommandDispatcher:
|
|||||||
cur.inspector.hide()
|
cur.inspector.hide()
|
||||||
else:
|
else:
|
||||||
if not config.get('general', 'developer-extras'):
|
if not config.get('general', 'developer-extras'):
|
||||||
raise CommandError("Please enable developer-extras before "
|
raise cmdexc.CommandError(
|
||||||
"using the webinspector!")
|
"Please enable developer-extras before using the "
|
||||||
|
"webinspector!")
|
||||||
else:
|
else:
|
||||||
cur.inspector.show()
|
cur.inspector.show()
|
||||||
|
|
||||||
@ -739,7 +741,8 @@ class CommandDispatcher:
|
|||||||
page = self._tabs.currentWidget().page()
|
page = self._tabs.currentWidget().page()
|
||||||
self._tabs.download_get.emit(self._tabs.current_url(), page)
|
self._tabs.download_get.emit(self._tabs.current_url(), page)
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.tabs.cmd', modes=[KeyMode.insert],
|
@cmdutils.register(instance='mainwindow.tabs.cmd',
|
||||||
|
modes=[usertypes.KeyMode.insert],
|
||||||
hide=True)
|
hide=True)
|
||||||
def open_editor(self):
|
def open_editor(self):
|
||||||
"""Open an external editor with the currently selected form field.
|
"""Open an external editor with the currently selected form field.
|
||||||
@ -756,14 +759,14 @@ class CommandDispatcher:
|
|||||||
frame = self._tabs.currentWidget().page().currentFrame()
|
frame = self._tabs.currentWidget().page().currentFrame()
|
||||||
elem = webelem.focus_elem(frame)
|
elem = webelem.focus_elem(frame)
|
||||||
if elem.isNull():
|
if elem.isNull():
|
||||||
raise CommandError("No element focused!")
|
raise cmdexc.CommandError("No element focused!")
|
||||||
if not webelem.is_editable(elem, strict=True):
|
if not webelem.is_editable(elem, strict=True):
|
||||||
raise CommandError("Focused element is not editable!")
|
raise cmdexc.CommandError("Focused element is not editable!")
|
||||||
if webelem.is_content_editable(elem):
|
if webelem.is_content_editable(elem):
|
||||||
text = elem.toPlainText()
|
text = elem.toPlainText()
|
||||||
else:
|
else:
|
||||||
text = elem.evaluateJavaScript('this.value')
|
text = elem.evaluateJavaScript('this.value')
|
||||||
self._editor = ExternalEditor(self._tabs)
|
self._editor = editor.ExternalEditor(self._tabs)
|
||||||
self._editor.editing_finished.connect(
|
self._editor.editing_finished.connect(
|
||||||
partial(self.on_editing_finished, elem))
|
partial(self.on_editing_finished, elem))
|
||||||
self._editor.edit(text)
|
self._editor.edit(text)
|
||||||
@ -778,7 +781,7 @@ class CommandDispatcher:
|
|||||||
text: The new text to insert.
|
text: The new text to insert.
|
||||||
"""
|
"""
|
||||||
if elem.isNull():
|
if elem.isNull():
|
||||||
raise CommandError("Element vanished while editing!")
|
raise cmdexc.CommandError("Element vanished while editing!")
|
||||||
if webelem.is_content_editable(elem):
|
if webelem.is_content_editable(elem):
|
||||||
log.misc.debug("Filling element {} via setPlainText.".format(
|
log.misc.debug("Filling element {} via setPlainText.".format(
|
||||||
webelem.debug_text(elem)))
|
webelem.debug_text(elem)))
|
||||||
|
@ -22,9 +22,8 @@
|
|||||||
from PyQt5.QtNetwork import QNetworkCookie, QNetworkCookieJar
|
from PyQt5.QtNetwork import QNetworkCookie, QNetworkCookieJar
|
||||||
from PyQt5.QtCore import QStandardPaths, QDateTime
|
from PyQt5.QtCore import QStandardPaths, QDateTime
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config, lineparser
|
||||||
from qutebrowser.config.lineparser import LineConfigParser
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.misc import get_standard_dir
|
|
||||||
|
|
||||||
|
|
||||||
class CookieJar(QNetworkCookieJar):
|
class CookieJar(QNetworkCookieJar):
|
||||||
@ -33,8 +32,8 @@ class CookieJar(QNetworkCookieJar):
|
|||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
datadir = get_standard_dir(QStandardPaths.DataLocation)
|
datadir = utils.get_standard_dir(QStandardPaths.DataLocation)
|
||||||
self._linecp = LineConfigParser(datadir, 'cookies')
|
self._linecp = lineparser.LineConfigParser(datadir, 'cookies')
|
||||||
cookies = []
|
cookies = []
|
||||||
for line in self._linecp:
|
for line in self._linecp:
|
||||||
cookies += QNetworkCookie.parseCookies(line.encode('utf-8'))
|
cookies += QNetworkCookie.parseCookies(line.encode('utf-8'))
|
||||||
|
@ -21,21 +21,19 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
from functools import partial
|
import functools
|
||||||
from collections import deque
|
import collections
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QTimer, QStandardPaths
|
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QTimer, QStandardPaths
|
||||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
|
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.commands import utils as cmdutils
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
import qutebrowser.utils.misc as utils
|
from qutebrowser.utils import message, http, usertypes
|
||||||
from qutebrowser.utils.http import parse_content_disposition
|
from qutebrowser.utils import misc as utils
|
||||||
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.log import downloads as logger
|
from qutebrowser.utils.log import downloads as logger
|
||||||
from qutebrowser.utils.usertypes import PromptMode, Question, Timer
|
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
|
||||||
|
|
||||||
|
|
||||||
class DownloadItem(QObject):
|
class DownloadItem(QObject):
|
||||||
@ -92,7 +90,7 @@ class DownloadItem(QObject):
|
|||||||
self.basename = '???'
|
self.basename = '???'
|
||||||
samples = int(self.SPEED_AVG_WINDOW *
|
samples = int(self.SPEED_AVG_WINDOW *
|
||||||
(1000 / self.SPEED_REFRESH_INTERVAL))
|
(1000 / self.SPEED_REFRESH_INTERVAL))
|
||||||
self.speed_avg = deque(maxlen=samples)
|
self.speed_avg = collections.deque(maxlen=samples)
|
||||||
self.fileobj = None
|
self.fileobj = None
|
||||||
self.filename = None
|
self.filename = None
|
||||||
self.is_cancelled = False
|
self.is_cancelled = False
|
||||||
@ -111,7 +109,7 @@ class DownloadItem(QObject):
|
|||||||
QTimer.singleShot(0, lambda: self.error.emit(reply.errorString()))
|
QTimer.singleShot(0, lambda: self.error.emit(reply.errorString()))
|
||||||
if reply.isFinished():
|
if reply.isFinished():
|
||||||
QTimer.singleShot(0, self.finished.emit)
|
QTimer.singleShot(0, self.finished.emit)
|
||||||
self.timer = Timer(self, 'speed_refresh')
|
self.timer = usertypes.Timer(self, 'speed_refresh')
|
||||||
self.timer.timeout.connect(self.update_speed)
|
self.timer.timeout.connect(self.update_speed)
|
||||||
self.timer.setInterval(self.SPEED_REFRESH_INTERVAL)
|
self.timer.setInterval(self.SPEED_REFRESH_INTERVAL)
|
||||||
self.timer.start()
|
self.timer.start()
|
||||||
@ -349,7 +347,7 @@ class DownloadManager(QObject):
|
|||||||
url: The URL to get, as QUrl
|
url: The URL to get, as QUrl
|
||||||
page: The QWebPage to get the download from.
|
page: The QWebPage to get the download from.
|
||||||
"""
|
"""
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
req = QNetworkRequest(url)
|
req = QNetworkRequest(url)
|
||||||
reply = page.networkAccessManager().get(req)
|
reply = page.networkAccessManager().get(req)
|
||||||
self.fetch(reply)
|
self.fetch(reply)
|
||||||
@ -362,7 +360,7 @@ class DownloadManager(QObject):
|
|||||||
try:
|
try:
|
||||||
download = self.downloads[count - 1]
|
download = self.downloads[count - 1]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise CommandError("There's no download {}!".format(count))
|
raise cmdexc.CommandError("There's no download {}!".format(count))
|
||||||
download.cancel()
|
download.cancel()
|
||||||
|
|
||||||
@pyqtSlot('QNetworkReply')
|
@pyqtSlot('QNetworkReply')
|
||||||
@ -372,25 +370,27 @@ class DownloadManager(QObject):
|
|||||||
Args:
|
Args:
|
||||||
reply: The QNetworkReply to download.
|
reply: The QNetworkReply to download.
|
||||||
"""
|
"""
|
||||||
_inline, suggested_filename = parse_content_disposition(reply)
|
_inline, suggested_filename = http.parse_content_disposition(reply)
|
||||||
logger.debug("fetch: {} -> {}".format(reply.url(), suggested_filename))
|
logger.debug("fetch: {} -> {}".format(reply.url(), suggested_filename))
|
||||||
download = DownloadItem(reply, self)
|
download = DownloadItem(reply, self)
|
||||||
download.finished.connect(partial(self.on_finished, download))
|
download.finished.connect(
|
||||||
download.data_changed.connect(partial(self.on_data_changed, download))
|
functools.partial(self.on_finished, download))
|
||||||
|
download.data_changed.connect(
|
||||||
|
functools.partial(self.on_data_changed, download))
|
||||||
download.error.connect(self.on_error)
|
download.error.connect(self.on_error)
|
||||||
download.basename = suggested_filename
|
download.basename = suggested_filename
|
||||||
self.download_about_to_be_added.emit(len(self.downloads) + 1)
|
self.download_about_to_be_added.emit(len(self.downloads) + 1)
|
||||||
self.downloads.append(download)
|
self.downloads.append(download)
|
||||||
self.download_added.emit()
|
self.download_added.emit()
|
||||||
|
|
||||||
q = Question(self)
|
q = usertypes.Question(self)
|
||||||
q.text = "Save file to:"
|
q.text = "Save file to:"
|
||||||
q.mode = PromptMode.text
|
q.mode = usertypes.PromptMode.text
|
||||||
q.default = suggested_filename
|
q.default = suggested_filename
|
||||||
q.answered.connect(download.set_filename)
|
q.answered.connect(download.set_filename)
|
||||||
q.cancelled.connect(download.cancel)
|
q.cancelled.connect(download.cancel)
|
||||||
q.completed.connect(q.deleteLater)
|
q.completed.connect(q.deleteLater)
|
||||||
q.destroyed.connect(partial(self.questions.remove, q))
|
q.destroyed.connect(functools.partial(self.questions.remove, q))
|
||||||
self.questions.append(q)
|
self.questions.append(q)
|
||||||
download.cancelled.connect(q.abort)
|
download.cancelled.connect(q.abort)
|
||||||
message.instance().ask(q, blocking=False)
|
message.instance().ask(q, blocking=False)
|
||||||
|
@ -21,28 +21,28 @@
|
|||||||
|
|
||||||
import math
|
import math
|
||||||
import subprocess
|
import subprocess
|
||||||
from collections import namedtuple
|
import collections
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent, Qt, QUrl
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent, Qt, QUrl
|
||||||
from PyQt5.QtGui import QMouseEvent, QClipboard
|
from PyQt5.QtGui import QMouseEvent, QClipboard
|
||||||
from PyQt5.QtWidgets import QApplication
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
import qutebrowser.keyinput.modeman as modeman
|
from qutebrowser.keyinput import modeman
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.utils import message, webelem
|
||||||
import qutebrowser.utils.webelem as webelem
|
from qutebrowser.commands import userscripts
|
||||||
import qutebrowser.commands.userscripts as userscripts
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.usertypes import enum, KeyMode
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.log import hints as logger
|
from qutebrowser.utils.log import hints as logger
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
|
||||||
|
|
||||||
|
|
||||||
ElemTuple = namedtuple('ElemTuple', 'elem, label')
|
ElemTuple = collections.namedtuple('ElemTuple', 'elem, label')
|
||||||
|
|
||||||
|
|
||||||
Target = enum('Target', 'normal', 'tab', 'tab_bg', 'yank', 'yank_primary',
|
Target = usertypes.enum('Target', 'normal', 'tab', 'tab_bg', 'yank',
|
||||||
'fill', 'rapid', 'download', 'userscript', 'spawn')
|
'yank_primary', 'fill', 'rapid', 'download',
|
||||||
|
'userscript', 'spawn')
|
||||||
|
|
||||||
|
|
||||||
class HintContext:
|
class HintContext:
|
||||||
@ -340,7 +340,7 @@ class HintManager(QObject):
|
|||||||
Args:
|
Args:
|
||||||
url: The URL to open as a QURL.
|
url: The URL to open as a QURL.
|
||||||
"""
|
"""
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
sel = self._context.target == Target.yank_primary
|
sel = self._context.target == Target.yank_primary
|
||||||
mode = QClipboard.Selection if sel else QClipboard.Clipboard
|
mode = QClipboard.Selection if sel else QClipboard.Clipboard
|
||||||
urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
|
urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
|
||||||
@ -354,7 +354,7 @@ class HintManager(QObject):
|
|||||||
Args:
|
Args:
|
||||||
url: The URL to open as a QUrl.
|
url: The URL to open as a QUrl.
|
||||||
"""
|
"""
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
urlstr = url.toDisplayString(QUrl.FullyEncoded)
|
urlstr = url.toDisplayString(QUrl.FullyEncoded)
|
||||||
args = self._context.get_args(urlstr)
|
args = self._context.get_args(urlstr)
|
||||||
message.set_cmd_text(' '.join(args))
|
message.set_cmd_text(' '.join(args))
|
||||||
@ -370,19 +370,19 @@ class HintManager(QObject):
|
|||||||
message.error("No suitable link found for this element.",
|
message.error("No suitable link found for this element.",
|
||||||
immediately=True)
|
immediately=True)
|
||||||
return
|
return
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
self.download_get.emit(url, elem.webFrame().page())
|
self.download_get.emit(url, elem.webFrame().page())
|
||||||
|
|
||||||
def _call_userscript(self, url):
|
def _call_userscript(self, url):
|
||||||
"""Call an userscript from a hint."""
|
"""Call an userscript from a hint."""
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
cmd = self._context.args[0]
|
cmd = self._context.args[0]
|
||||||
args = self._context.args[1:]
|
args = self._context.args[1:]
|
||||||
userscripts.run(cmd, *args, url=url)
|
userscripts.run(cmd, *args, url=url)
|
||||||
|
|
||||||
def _spawn(self, url):
|
def _spawn(self, url):
|
||||||
"""Spawn a simple command from a hint."""
|
"""Spawn a simple command from a hint."""
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
|
urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
|
||||||
args = self._context.get_args(urlstr)
|
args = self._context.get_args(urlstr)
|
||||||
subprocess.Popen(args)
|
subprocess.Popen(args)
|
||||||
@ -406,7 +406,7 @@ class HintManager(QObject):
|
|||||||
url = QUrl(text)
|
url = QUrl(text)
|
||||||
if url.isRelative():
|
if url.isRelative():
|
||||||
url = baseurl.resolved(url)
|
url = baseurl.resolved(url)
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def _find_prevnext(self, frame, prev=False):
|
def _find_prevnext(self, frame, prev=False):
|
||||||
@ -457,11 +457,11 @@ class HintManager(QObject):
|
|||||||
"""
|
"""
|
||||||
elem = self._find_prevnext(frame, prev)
|
elem = self._find_prevnext(frame, prev)
|
||||||
if elem is None:
|
if elem is None:
|
||||||
raise CommandError("No {} links found!".format(
|
raise cmdexc.CommandError("No {} links found!".format(
|
||||||
"prev" if prev else "forward"))
|
"prev" if prev else "forward"))
|
||||||
url = self._resolve_url(elem, baseurl)
|
url = self._resolve_url(elem, baseurl)
|
||||||
if url is None or not url.isValid():
|
if url is None or not url.isValid():
|
||||||
raise CommandError("No {} links found!".format(
|
raise cmdexc.CommandError("No {} links found!".format(
|
||||||
"prev" if prev else "forward"))
|
"prev" if prev else "forward"))
|
||||||
self.openurl.emit(url, newtab)
|
self.openurl.emit(url, newtab)
|
||||||
|
|
||||||
@ -488,12 +488,13 @@ class HintManager(QObject):
|
|||||||
raise ValueError("start() was called with frame=None")
|
raise ValueError("start() was called with frame=None")
|
||||||
if target in (Target.userscript, Target.spawn, Target.fill):
|
if target in (Target.userscript, Target.spawn, Target.fill):
|
||||||
if not args:
|
if not args:
|
||||||
raise CommandError("Additional arguments are required with "
|
raise cmdexc.CommandError(
|
||||||
"target userscript/spawn/fill.")
|
"Additional arguments are required with target "
|
||||||
|
"userscript/spawn/fill.")
|
||||||
else:
|
else:
|
||||||
if args:
|
if args:
|
||||||
raise CommandError("Arguments are only allowed with target "
|
raise cmdexc.CommandError(
|
||||||
"userscript/spawn.")
|
"Arguments are only allowed with target userscript/spawn.")
|
||||||
elems = []
|
elems = []
|
||||||
ctx = HintContext()
|
ctx = HintContext()
|
||||||
ctx.frames = webelem.get_child_frames(mainframe)
|
ctx.frames = webelem.get_child_frames(mainframe)
|
||||||
@ -503,7 +504,7 @@ class HintManager(QObject):
|
|||||||
visible_elems = [e for e in elems if filterfunc(e) and
|
visible_elems = [e for e in elems if filterfunc(e) and
|
||||||
webelem.is_visible(e, mainframe)]
|
webelem.is_visible(e, mainframe)]
|
||||||
if not visible_elems:
|
if not visible_elems:
|
||||||
raise CommandError("No elements found.")
|
raise cmdexc.CommandError("No elements found.")
|
||||||
ctx.target = target
|
ctx.target = target
|
||||||
ctx.baseurl = baseurl
|
ctx.baseurl = baseurl
|
||||||
ctx.args = args
|
ctx.args = args
|
||||||
@ -516,7 +517,7 @@ class HintManager(QObject):
|
|||||||
self._connect_frame_signals()
|
self._connect_frame_signals()
|
||||||
self.hint_strings_updated.emit(strings)
|
self.hint_strings_updated.emit(strings)
|
||||||
try:
|
try:
|
||||||
modeman.enter(KeyMode.hint, 'HintManager.start')
|
modeman.enter(usertypes.KeyMode.hint, 'HintManager.start')
|
||||||
except modeman.ModeLockedError:
|
except modeman.ModeLockedError:
|
||||||
self._cleanup()
|
self._cleanup()
|
||||||
|
|
||||||
@ -560,7 +561,7 @@ class HintManager(QObject):
|
|||||||
visible[k] = e
|
visible[k] = e
|
||||||
if not visible:
|
if not visible:
|
||||||
# Whoops, filtered all hints
|
# Whoops, filtered all hints
|
||||||
modeman.leave(KeyMode.hint, 'all filtered')
|
modeman.leave(usertypes.KeyMode.hint, 'all filtered')
|
||||||
elif len(visible) == 1 and config.get('hints', 'auto-follow'):
|
elif len(visible) == 1 and config.get('hints', 'auto-follow'):
|
||||||
# unpacking gets us the first (and only) key in the dict.
|
# unpacking gets us the first (and only) key in the dict.
|
||||||
self.fire(*visible)
|
self.fire(*visible)
|
||||||
@ -606,12 +607,12 @@ class HintManager(QObject):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("No suitable handler found!")
|
raise ValueError("No suitable handler found!")
|
||||||
if self._context.target != Target.rapid:
|
if self._context.target != Target.rapid:
|
||||||
modeman.maybe_leave(KeyMode.hint, 'followed')
|
modeman.maybe_leave(usertypes.KeyMode.hint, 'followed')
|
||||||
|
|
||||||
def follow_hint(self):
|
def follow_hint(self):
|
||||||
"""Follow the currently selected hint."""
|
"""Follow the currently selected hint."""
|
||||||
if not self._context.to_follow:
|
if not self._context.to_follow:
|
||||||
raise CommandError("No hint to follow")
|
raise cmdexc.CommandError("No hint to follow")
|
||||||
self.fire(self._context.to_follow, force=True)
|
self.fire(self._context.to_follow, force=True)
|
||||||
|
|
||||||
@pyqtSlot('QSize')
|
@pyqtSlot('QSize')
|
||||||
@ -627,16 +628,16 @@ class HintManager(QObject):
|
|||||||
css = self._get_hint_css(elems.elem, elems.label)
|
css = self._get_hint_css(elems.elem, elems.label)
|
||||||
elems.label.setAttribute('style', css)
|
elems.label.setAttribute('style', css)
|
||||||
|
|
||||||
@pyqtSlot(KeyMode)
|
@pyqtSlot(usertypes.KeyMode)
|
||||||
def on_mode_entered(self, mode):
|
def on_mode_entered(self, mode):
|
||||||
"""Stop hinting when insert mode was entered."""
|
"""Stop hinting when insert mode was entered."""
|
||||||
if mode == KeyMode.insert:
|
if mode == usertypes.KeyMode.insert:
|
||||||
modeman.maybe_leave(KeyMode.hint, 'insert mode')
|
modeman.maybe_leave(usertypes.KeyMode.hint, 'insert mode')
|
||||||
|
|
||||||
@pyqtSlot(KeyMode)
|
@pyqtSlot(usertypes.KeyMode)
|
||||||
def on_mode_left(self, mode):
|
def on_mode_left(self, mode):
|
||||||
"""Stop hinting when hinting mode was left."""
|
"""Stop hinting when hinting mode was left."""
|
||||||
if mode != KeyMode.hint or self._context is None:
|
if mode != usertypes.KeyMode.hint or self._context is None:
|
||||||
# We have one HintManager per tab, so when this gets called,
|
# We have one HintManager per tab, so when this gets called,
|
||||||
# self._context might be None, because the current tab is not
|
# self._context might be None, because the current tab is not
|
||||||
# hinting.
|
# hinting.
|
||||||
|
@ -24,29 +24,28 @@ OrderedDict. This is because we read them from a file at start and write them
|
|||||||
to a file on shutdown, so it makes semse to keep them as strings her.e
|
to a file on shutdown, so it makes semse to keep them as strings her.e
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from functools import partial
|
import functools
|
||||||
from collections import OrderedDict
|
import collections
|
||||||
|
|
||||||
from PyQt5.QtCore import QStandardPaths, QUrl
|
from PyQt5.QtCore import QStandardPaths, QUrl
|
||||||
|
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.utils import message, usertypes
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.usertypes import PromptMode
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.config.lineparser import LineConfigParser
|
from qutebrowser.commands import utils as cmdutils
|
||||||
from qutebrowser.utils.misc import get_standard_dir
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
from qutebrowser.config import lineparser
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
|
||||||
|
|
||||||
|
|
||||||
marks = OrderedDict()
|
marks = collections.OrderedDict()
|
||||||
linecp = None
|
linecp = None
|
||||||
|
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
"""Read quickmarks from the config file."""
|
"""Read quickmarks from the config file."""
|
||||||
global linecp
|
global linecp
|
||||||
confdir = get_standard_dir(QStandardPaths.ConfigLocation)
|
confdir = utils.get_standard_dir(QStandardPaths.ConfigLocation)
|
||||||
linecp = LineConfigParser(confdir, 'quickmarks')
|
linecp = lineparser.LineConfigParser(confdir, 'quickmarks')
|
||||||
for line in linecp:
|
for line in linecp:
|
||||||
try:
|
try:
|
||||||
key, url = line.split(maxsplit=1)
|
key, url = line.split(maxsplit=1)
|
||||||
@ -68,10 +67,10 @@ def prompt_save(url):
|
|||||||
Args:
|
Args:
|
||||||
url: The quickmark url as a QUrl.
|
url: The quickmark url as a QUrl.
|
||||||
"""
|
"""
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
|
urlstr = url.toString(QUrl.RemovePassword | QUrl.FullyEncoded)
|
||||||
message.ask_async("Add quickmark:", PromptMode.text,
|
message.ask_async("Add quickmark:", usertypes.PromptMode.text,
|
||||||
partial(quickmark_add, urlstr))
|
functools.partial(quickmark_add, urlstr))
|
||||||
|
|
||||||
|
|
||||||
@cmdutils.register()
|
@cmdutils.register()
|
||||||
@ -83,9 +82,9 @@ def quickmark_add(urlstr, name):
|
|||||||
name: The name for the new quickmark.
|
name: The name for the new quickmark.
|
||||||
"""
|
"""
|
||||||
if not name:
|
if not name:
|
||||||
raise CommandError("Can't set mark with empty name!")
|
raise cmdexc.CommandError("Can't set mark with empty name!")
|
||||||
if not urlstr:
|
if not urlstr:
|
||||||
raise CommandError("Can't set mark with empty URL!")
|
raise cmdexc.CommandError("Can't set mark with empty URL!")
|
||||||
|
|
||||||
def set_mark():
|
def set_mark():
|
||||||
"""Really set the quickmark."""
|
"""Really set the quickmark."""
|
||||||
@ -101,10 +100,12 @@ def quickmark_add(urlstr, name):
|
|||||||
def get(name):
|
def get(name):
|
||||||
"""Get the URL of the quickmark named name as a QUrl."""
|
"""Get the URL of the quickmark named name as a QUrl."""
|
||||||
if name not in marks:
|
if name not in marks:
|
||||||
raise CommandError("Quickmark '{}' does not exist!".format(name))
|
raise cmdexc.CommandError(
|
||||||
|
"Quickmark '{}' does not exist!".format(name))
|
||||||
urlstr = marks[name]
|
urlstr = marks[name]
|
||||||
url = QUrl(urlstr)
|
url = QUrl(urlstr)
|
||||||
if not url.isValid():
|
if not url.isValid():
|
||||||
raise CommandError("Invalid URL for quickmark {}: {} ({})".format(
|
raise cmdexc.CommandError(
|
||||||
name, urlstr, url.errorString()))
|
"Invalid URL for quickmark {}: {} ({})".format(name, urlstr,
|
||||||
|
url.errorString()))
|
||||||
return url
|
return url
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
|
|
||||||
"""A filter for signals which either filters or passes them."""
|
"""A filter for signals which either filters or passes them."""
|
||||||
|
|
||||||
from functools import partial
|
import functools
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject
|
from PyQt5.QtCore import QObject
|
||||||
|
|
||||||
from qutebrowser.utils.debug import dbg_signal, signal_name
|
from qutebrowser.utils import debug
|
||||||
from qutebrowser.widgets.webview import WebView
|
from qutebrowser.widgets import webview
|
||||||
from qutebrowser.utils.log import signals as logger
|
from qutebrowser.utils.log import signals as logger
|
||||||
|
|
||||||
|
|
||||||
@ -58,10 +58,10 @@ class SignalFilter(QObject):
|
|||||||
Return:
|
Return:
|
||||||
A partial functon calling _filter_signals with a signal.
|
A partial functon calling _filter_signals with a signal.
|
||||||
"""
|
"""
|
||||||
if not isinstance(tab, WebView):
|
if not isinstance(tab, webview.WebView):
|
||||||
raise ValueError("Tried to create filter for {} which is no "
|
raise ValueError("Tried to create filter for {} which is no "
|
||||||
"WebView!".format(tab))
|
"WebView!".format(tab))
|
||||||
return partial(self._filter_signals, signal, tab)
|
return functools.partial(self._filter_signals, signal, tab)
|
||||||
|
|
||||||
def _filter_signals(self, signal, tab, *args):
|
def _filter_signals(self, signal, tab, *args):
|
||||||
"""Filter signals and trigger TabbedBrowser signals if needed.
|
"""Filter signals and trigger TabbedBrowser signals if needed.
|
||||||
@ -80,7 +80,7 @@ class SignalFilter(QObject):
|
|||||||
Emit:
|
Emit:
|
||||||
The target signal if the sender was the current widget.
|
The target signal if the sender was the current widget.
|
||||||
"""
|
"""
|
||||||
log_signal = signal_name(signal) not in self.BLACKLIST
|
log_signal = debug.signal_name(signal) not in self.BLACKLIST
|
||||||
try:
|
try:
|
||||||
tabidx = self._tabs.indexOf(tab)
|
tabidx = self._tabs.indexOf(tab)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
@ -89,9 +89,9 @@ class SignalFilter(QObject):
|
|||||||
if tabidx == self._tabs.currentIndex():
|
if tabidx == self._tabs.currentIndex():
|
||||||
if log_signal:
|
if log_signal:
|
||||||
logger.debug("emitting: {} (tab {})".format(
|
logger.debug("emitting: {} (tab {})".format(
|
||||||
dbg_signal(signal, args), tabidx))
|
debug.dbg_signal(signal, args), tabidx))
|
||||||
signal.emit(*args)
|
signal.emit(*args)
|
||||||
else:
|
else:
|
||||||
if log_signal:
|
if log_signal:
|
||||||
logger.debug("ignoring: {} (tab {})".format(
|
logger.debug("ignoring: {} (tab {})".format(
|
||||||
dbg_signal(signal, args), tabidx))
|
debug.dbg_signal(signal, args), tabidx))
|
||||||
|
@ -28,14 +28,11 @@ from PyQt5.QtWidgets import QFileDialog
|
|||||||
from PyQt5.QtPrintSupport import QPrintDialog
|
from PyQt5.QtPrintSupport import QPrintDialog
|
||||||
from PyQt5.QtWebKitWidgets import QWebPage
|
from PyQt5.QtWebKitWidgets import QWebPage
|
||||||
|
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.config import config
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.network import networkmanager
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.utils import message, usertypes, log, http
|
||||||
import qutebrowser.utils.http as http
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.network.networkmanager import NetworkManager
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.misc import read_file
|
|
||||||
from qutebrowser.utils.qt import check_print_compat
|
|
||||||
from qutebrowser.utils.usertypes import PromptMode, ClickTarget
|
|
||||||
|
|
||||||
|
|
||||||
class BrowserPage(QWebPage):
|
class BrowserPage(QWebPage):
|
||||||
@ -61,7 +58,7 @@ class BrowserPage(QWebPage):
|
|||||||
QWebPage.ErrorPageExtension: self._handle_errorpage,
|
QWebPage.ErrorPageExtension: self._handle_errorpage,
|
||||||
QWebPage.ChooseMultipleFilesExtension: self._handle_multiple_files,
|
QWebPage.ChooseMultipleFilesExtension: self._handle_multiple_files,
|
||||||
}
|
}
|
||||||
self._networkmanager = NetworkManager(self)
|
self._networkmanager = networkmanager.NetworkManager(self)
|
||||||
self.setNetworkAccessManager(self._networkmanager)
|
self.setNetworkAccessManager(self._networkmanager)
|
||||||
self.setForwardUnsupportedContent(True)
|
self.setForwardUnsupportedContent(True)
|
||||||
self.printRequested.connect(self.on_print_requested)
|
self.printRequested.connect(self.on_print_requested)
|
||||||
@ -83,7 +80,8 @@ class BrowserPage(QWebPage):
|
|||||||
|
|
||||||
http://www.riverbankcomputing.com/pipermail/pyqt/2014-June/034385.html
|
http://www.riverbankcomputing.com/pipermail/pyqt/2014-June/034385.html
|
||||||
"""
|
"""
|
||||||
answer = message.ask("js: {}".format(msg), PromptMode.text, default)
|
answer = message.ask("js: {}".format(msg), usertypes.PromptMode.text,
|
||||||
|
default)
|
||||||
if answer is None:
|
if answer is None:
|
||||||
return (False, "")
|
return (False, "")
|
||||||
else:
|
else:
|
||||||
@ -122,7 +120,7 @@ class BrowserPage(QWebPage):
|
|||||||
log.webview.debug("Error domain: {}, error code: {}".format(
|
log.webview.debug("Error domain: {}, error code: {}".format(
|
||||||
info.domain, info.error))
|
info.domain, info.error))
|
||||||
title = "Error loading page: {}".format(urlstr)
|
title = "Error loading page: {}".format(urlstr)
|
||||||
errpage.content = read_file('html/error.html').format(
|
errpage.content = utils.read_file('html/error.html').format(
|
||||||
title=title, url=urlstr, error=info.errorString, icon='')
|
title=title, url=urlstr, error=info.errorString, icon='')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -158,7 +156,7 @@ class BrowserPage(QWebPage):
|
|||||||
|
|
||||||
def on_print_requested(self, frame):
|
def on_print_requested(self, frame):
|
||||||
"""Handle printing when requested via javascript."""
|
"""Handle printing when requested via javascript."""
|
||||||
if not check_print_compat():
|
if not qtutils.check_print_compat():
|
||||||
message.error("Printing on Qt < 5.3.0 on Windows is broken, "
|
message.error("Printing on Qt < 5.3.0 on Windows is broken, "
|
||||||
"please upgrade!", immediately=True)
|
"please upgrade!", immediately=True)
|
||||||
return
|
return
|
||||||
@ -246,11 +244,12 @@ class BrowserPage(QWebPage):
|
|||||||
|
|
||||||
def javaScriptAlert(self, _frame, msg):
|
def javaScriptAlert(self, _frame, msg):
|
||||||
"""Override javaScriptAlert to use the statusbar."""
|
"""Override javaScriptAlert to use the statusbar."""
|
||||||
message.ask("[js alert] {}".format(msg), PromptMode.alert)
|
message.ask("[js alert] {}".format(msg), usertypes.PromptMode.alert)
|
||||||
|
|
||||||
def javaScriptConfirm(self, _frame, msg):
|
def javaScriptConfirm(self, _frame, msg):
|
||||||
"""Override javaScriptConfirm to use the statusbar."""
|
"""Override javaScriptConfirm to use the statusbar."""
|
||||||
ans = message.ask("[js confirm] {}".format(msg), PromptMode.yesno)
|
ans = message.ask("[js confirm] {}".format(msg),
|
||||||
|
usertypes.PromptMode.yesno)
|
||||||
return bool(ans)
|
return bool(ans)
|
||||||
|
|
||||||
def javaScriptConsoleMessage(self, msg, line, source):
|
def javaScriptConsoleMessage(self, msg, line, source):
|
||||||
@ -270,7 +269,7 @@ class BrowserPage(QWebPage):
|
|||||||
def shouldInterruptJavaScript(self):
|
def shouldInterruptJavaScript(self):
|
||||||
"""Override shouldInterruptJavaScript to use the statusbar."""
|
"""Override shouldInterruptJavaScript to use the statusbar."""
|
||||||
answer = message.ask("Interrupt long-running javascript?",
|
answer = message.ask("Interrupt long-running javascript?",
|
||||||
PromptMode.yesno)
|
usertypes.PromptMode.yesno)
|
||||||
if answer is None:
|
if answer is None:
|
||||||
answer = True
|
answer = True
|
||||||
return answer
|
return answer
|
||||||
@ -298,10 +297,10 @@ class BrowserPage(QWebPage):
|
|||||||
message.error("Invalid link {} clicked!".format(urlstr))
|
message.error("Invalid link {} clicked!".format(urlstr))
|
||||||
log.webview.debug(url.errorString())
|
log.webview.debug(url.errorString())
|
||||||
return False
|
return False
|
||||||
if self._view.open_target == ClickTarget.tab:
|
if self._view.open_target == usertypes.ClickTarget.tab:
|
||||||
self._view.tabbedbrowser.tabopen(url, False)
|
self._view.tabbedbrowser.tabopen(url, False)
|
||||||
return False
|
return False
|
||||||
elif self._view.open_target == ClickTarget.tab_bg:
|
elif self._view.open_target == usertypes.ClickTarget.tab_bg:
|
||||||
self._view.tabbedbrowser.tabopen(url, True)
|
self._view.tabbedbrowser.tabopen(url, True)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
|
@ -22,9 +22,8 @@
|
|||||||
from PyQt5.QtCore import QCoreApplication, QUrl
|
from PyQt5.QtCore import QCoreApplication, QUrl
|
||||||
from PyQt5.QtWebKit import QWebSettings
|
from PyQt5.QtWebKit import QWebSettings
|
||||||
|
|
||||||
from qutebrowser.commands.exceptions import (ArgumentCountError,
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
PrerequisitesError)
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.misc import dotted_getattr
|
|
||||||
from qutebrowser.utils.log import commands as logger
|
from qutebrowser.utils.log import commands as logger
|
||||||
|
|
||||||
|
|
||||||
@ -84,16 +83,18 @@ class Command:
|
|||||||
curmode = QCoreApplication.instance().modeman.mode
|
curmode = QCoreApplication.instance().modeman.mode
|
||||||
if self.modes is not None and curmode not in self.modes:
|
if self.modes is not None and curmode not in self.modes:
|
||||||
mode_names = '/'.join(mode.name for mode in self.modes)
|
mode_names = '/'.join(mode.name for mode in self.modes)
|
||||||
raise PrerequisitesError("{}: This command is only allowed in {} "
|
raise cmdexc.PrerequisitesError(
|
||||||
"mode.".format(self.name, mode_names))
|
"{}: This command is only allowed in {} mode.".format(
|
||||||
|
self.name, mode_names))
|
||||||
elif self.not_modes is not None and curmode in self.not_modes:
|
elif self.not_modes is not None and curmode in self.not_modes:
|
||||||
mode_names = '/'.join(mode.name for mode in self.not_modes)
|
mode_names = '/'.join(mode.name for mode in self.not_modes)
|
||||||
raise PrerequisitesError("{}: This command is not allowed in {} "
|
raise cmdexc.PrerequisitesError(
|
||||||
"mode.".format(self.name, mode_names))
|
"{}: This command is not allowed in {} mode.".format(
|
||||||
|
self.name, mode_names))
|
||||||
if self.needs_js and not QWebSettings.globalSettings().testAttribute(
|
if self.needs_js and not QWebSettings.globalSettings().testAttribute(
|
||||||
QWebSettings.JavascriptEnabled):
|
QWebSettings.JavascriptEnabled):
|
||||||
raise PrerequisitesError("{}: This command needs javascript "
|
raise cmdexc.PrerequisitesError(
|
||||||
"enabled.".format(self.name))
|
"{}: This command needs javascript enabled.".format(self.name))
|
||||||
if self.nargs[1] is None and self.nargs[0] <= len(args):
|
if self.nargs[1] is None and self.nargs[0] <= len(args):
|
||||||
pass
|
pass
|
||||||
elif self.nargs[0] <= len(args) <= self.nargs[1]:
|
elif self.nargs[0] <= len(args) <= self.nargs[1]:
|
||||||
@ -105,8 +106,9 @@ class Command:
|
|||||||
argcnt = '{}-inf'.format(self.nargs[0])
|
argcnt = '{}-inf'.format(self.nargs[0])
|
||||||
else:
|
else:
|
||||||
argcnt = '{}-{}'.format(self.nargs[0], self.nargs[1])
|
argcnt = '{}-{}'.format(self.nargs[0], self.nargs[1])
|
||||||
raise ArgumentCountError("{}: {} args expected, but got {}".format(
|
raise cmdexc.ArgumentCountError(
|
||||||
self.name, argcnt, len(args)))
|
"{}: {} args expected, but got {}".format(self.name, argcnt,
|
||||||
|
len(args)))
|
||||||
|
|
||||||
def run(self, args=None, count=None):
|
def run(self, args=None, count=None):
|
||||||
"""Run the command.
|
"""Run the command.
|
||||||
@ -142,7 +144,7 @@ class Command:
|
|||||||
if self.instance == '':
|
if self.instance == '':
|
||||||
obj = app
|
obj = app
|
||||||
else:
|
else:
|
||||||
obj = dotted_getattr(app, self.instance)
|
obj = utils.dotted_getattr(app, self.instance)
|
||||||
new_args.insert(0, obj)
|
new_args.insert(0, obj)
|
||||||
|
|
||||||
if count is not None and self.count:
|
if count is not None and self.count:
|
||||||
|
@ -22,12 +22,11 @@
|
|||||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
|
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
|
||||||
from PyQt5.QtWebKitWidgets import QWebPage
|
from PyQt5.QtWebKitWidgets import QWebPage
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import utils as cmdutils
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
from qutebrowser.commands.exceptions import (NoSuchCommandError,
|
from qutebrowser.utils import message
|
||||||
CommandMetaError, CommandError)
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.misc import safe_shlex_split
|
|
||||||
from qutebrowser.utils.log import commands as logger
|
from qutebrowser.utils.log import commands as logger
|
||||||
|
|
||||||
|
|
||||||
@ -201,7 +200,7 @@ class CommandRunner:
|
|||||||
"""
|
"""
|
||||||
parts = text.strip().split(maxsplit=1)
|
parts = text.strip().split(maxsplit=1)
|
||||||
if not parts:
|
if not parts:
|
||||||
raise NoSuchCommandError("No command given")
|
raise cmdexc.NoSuchCommandError("No command given")
|
||||||
cmdstr = parts[0]
|
cmdstr = parts[0]
|
||||||
if aliases:
|
if aliases:
|
||||||
new_cmd = self._get_alias(text, alias_no_args)
|
new_cmd = self._get_alias(text, alias_no_args)
|
||||||
@ -217,11 +216,12 @@ class CommandRunner:
|
|||||||
parts.append('')
|
parts.append('')
|
||||||
return parts
|
return parts
|
||||||
else:
|
else:
|
||||||
raise NoSuchCommandError('{}: no such command'.format(cmdstr))
|
raise cmdexc.NoSuchCommandError(
|
||||||
|
'{}: no such command'.format(cmdstr))
|
||||||
if len(parts) == 1:
|
if len(parts) == 1:
|
||||||
args = []
|
args = []
|
||||||
elif cmd.split:
|
elif cmd.split:
|
||||||
args = safe_shlex_split(parts[1])
|
args = utils.safe_shlex_split(parts[1])
|
||||||
else:
|
else:
|
||||||
args = parts[1].split(maxsplit=cmd.nargs[0] - 1)
|
args = parts[1].split(maxsplit=cmd.nargs[0] - 1)
|
||||||
self._cmd = cmd
|
self._cmd = cmd
|
||||||
@ -266,7 +266,7 @@ class CommandRunner:
|
|||||||
"""Run a command and display exceptions in the statusbar."""
|
"""Run a command and display exceptions in the statusbar."""
|
||||||
try:
|
try:
|
||||||
self.run(text, count)
|
self.run(text, count)
|
||||||
except (CommandMetaError, CommandError) as e:
|
except (cmdexc.CommandMetaError, cmdexc.CommandError) as e:
|
||||||
message.error(e, immediately=True)
|
message.error(e, immediately=True)
|
||||||
|
|
||||||
@pyqtSlot(str, int)
|
@pyqtSlot(str, int)
|
||||||
@ -277,5 +277,5 @@ class CommandRunner:
|
|||||||
suitable to use while initializing."""
|
suitable to use while initializing."""
|
||||||
try:
|
try:
|
||||||
self.run(text, count)
|
self.run(text, count)
|
||||||
except (CommandMetaError, CommandError) as e:
|
except (cmdexc.CommandMetaError, cmdexc.CommandError) as e:
|
||||||
message.error(e)
|
message.error(e)
|
||||||
|
@ -26,17 +26,17 @@ Module attributes:
|
|||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import tempfile
|
import tempfile
|
||||||
from select import select
|
import select
|
||||||
from functools import partial
|
import functools
|
||||||
|
|
||||||
from PyQt5.QtCore import (pyqtSignal, QObject, QThread, QStandardPaths,
|
from PyQt5.QtCore import (pyqtSignal, QObject, QThread, QStandardPaths,
|
||||||
QProcessEnvironment, QProcess, QUrl)
|
QProcessEnvironment, QProcess, QUrl)
|
||||||
|
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.utils import message
|
||||||
from qutebrowser.utils.misc import get_standard_dir
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.log import procs as logger
|
from qutebrowser.utils.log import procs as logger
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
from qutebrowser.commands import runners
|
||||||
from qutebrowser.commands.runners import CommandRunner
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
|
|
||||||
|
|
||||||
_runners = []
|
_runners = []
|
||||||
@ -83,7 +83,7 @@ class _BlockingFIFOReader(QObject):
|
|||||||
self.fifo = os.fdopen(fd, 'r')
|
self.fifo = os.fdopen(fd, 'r')
|
||||||
while True:
|
while True:
|
||||||
logger.debug("thread loop")
|
logger.debug("thread loop")
|
||||||
ready_r, _ready_w, _ready_e = select([self.fifo], [], [], 1)
|
ready_r, _ready_w, _ready_e = select.select([self.fifo], [], [], 1)
|
||||||
if ready_r:
|
if ready_r:
|
||||||
logger.debug("reading data")
|
logger.debug("reading data")
|
||||||
for line in self.fifo:
|
for line in self.fifo:
|
||||||
@ -205,7 +205,7 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner):
|
|||||||
self.thread = None
|
self.thread = None
|
||||||
|
|
||||||
def run(self, cmd, *args, env=None):
|
def run(self, cmd, *args, env=None):
|
||||||
rundir = get_standard_dir(QStandardPaths.RuntimeLocation)
|
rundir = utils.get_standard_dir(QStandardPaths.RuntimeLocation)
|
||||||
# tempfile.mktemp is deprecated and discouraged, but we use it here to
|
# tempfile.mktemp is deprecated and discouraged, but we use it here to
|
||||||
# create a FIFO since the only other alternative would be to create a
|
# create a FIFO since the only other alternative would be to create a
|
||||||
# directory and place the FIFO there, which sucks. Since os.kfifo will
|
# directory and place the FIFO there, which sucks. Since os.kfifo will
|
||||||
@ -313,7 +313,8 @@ class _DummyUserscriptRunner:
|
|||||||
def run(self, _cmd, *_args, _env=None):
|
def run(self, _cmd, *_args, _env=None):
|
||||||
"""Print an error as userscripts are not supported."""
|
"""Print an error as userscripts are not supported."""
|
||||||
self.finished.emit()
|
self.finished.emit()
|
||||||
raise CommandError("Userscripts are not supported on this platform!")
|
raise cmdexc.CommandError(
|
||||||
|
"Userscripts are not supported on this platform!")
|
||||||
|
|
||||||
|
|
||||||
# Here we basically just assign a generic UserscriptRunner class which does the
|
# Here we basically just assign a generic UserscriptRunner class which does the
|
||||||
@ -329,7 +330,7 @@ else:
|
|||||||
def init():
|
def init():
|
||||||
"""Initialize the global _commandrunner."""
|
"""Initialize the global _commandrunner."""
|
||||||
global _commandrunner
|
global _commandrunner
|
||||||
_commandrunner = CommandRunner()
|
_commandrunner = runners.CommandRunner()
|
||||||
|
|
||||||
|
|
||||||
def run(cmd, *args, url):
|
def run(cmd, *args, url):
|
||||||
@ -341,4 +342,4 @@ def run(cmd, *args, url):
|
|||||||
runner.got_cmd.connect(_commandrunner.run_safely)
|
runner.got_cmd.connect(_commandrunner.run_safely)
|
||||||
runner.run(cmd, *args, env={'QUTE_URL': urlstr})
|
runner.run(cmd, *args, env={'QUTE_URL': urlstr})
|
||||||
_runners.append(runner)
|
_runners.append(runner)
|
||||||
runner.finished.connect(partial(_runners.remove, runner))
|
runner.finished.connect(functools.partial(_runners.remove, runner))
|
||||||
|
@ -24,12 +24,12 @@ Module attributes:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
from collections import Iterable
|
import collections
|
||||||
|
|
||||||
import qutebrowser.utils.qt as qtutils
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.commands.command import Command
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
from qutebrowser.commands import command
|
||||||
from qutebrowser.utils.usertypes import KeyMode
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
|
|
||||||
cmd_dict = {}
|
cmd_dict = {}
|
||||||
|
|
||||||
@ -49,8 +49,9 @@ def check_overflow(arg, ctype):
|
|||||||
try:
|
try:
|
||||||
qtutils.check_overflow(arg, ctype)
|
qtutils.check_overflow(arg, ctype)
|
||||||
except OverflowError:
|
except OverflowError:
|
||||||
raise CommandError("Numeric argument is too large for internal {} "
|
raise cmdexc.CommandError(
|
||||||
"representation.".format(ctype))
|
"Numeric argument is too large for internal {} "
|
||||||
|
"representation.".format(ctype))
|
||||||
|
|
||||||
|
|
||||||
def arg_or_count(arg, count, default=None, countzero=None):
|
def arg_or_count(arg, count, default=None, countzero=None):
|
||||||
@ -135,11 +136,11 @@ class register: # pylint: disable=invalid-name
|
|||||||
self.debug = debug
|
self.debug = debug
|
||||||
if modes is not None:
|
if modes is not None:
|
||||||
for m in modes:
|
for m in modes:
|
||||||
if not isinstance(m, KeyMode):
|
if not isinstance(m, usertypes.KeyMode):
|
||||||
raise TypeError("Mode {} is no KeyMode member!".format(m))
|
raise TypeError("Mode {} is no KeyMode member!".format(m))
|
||||||
if not_modes is not None:
|
if not_modes is not None:
|
||||||
for m in not_modes:
|
for m in not_modes:
|
||||||
if not isinstance(m, KeyMode):
|
if not isinstance(m, usertypes.KeyMode):
|
||||||
raise TypeError("Mode {} is no KeyMode member!".format(m))
|
raise TypeError("Mode {} is no KeyMode member!".format(m))
|
||||||
|
|
||||||
def __call__(self, func):
|
def __call__(self, func):
|
||||||
@ -178,12 +179,11 @@ class register: # pylint: disable=invalid-name
|
|||||||
desc = func.__doc__.splitlines()[0].strip()
|
desc = func.__doc__.splitlines()[0].strip()
|
||||||
else:
|
else:
|
||||||
desc = ""
|
desc = ""
|
||||||
cmd = Command(name=mainname, split=self.split,
|
cmd = command.Command(
|
||||||
hide=self.hide, nargs=nargs, count=count, desc=desc,
|
name=mainname, split=self.split, hide=self.hide, nargs=nargs,
|
||||||
instance=self.instance, handler=func,
|
count=count, desc=desc, instance=self.instance, handler=func,
|
||||||
completion=self.completion, modes=self.modes,
|
completion=self.completion, modes=self.modes,
|
||||||
not_modes=self.not_modes, needs_js=self.needs_js,
|
not_modes=self.not_modes, needs_js=self.needs_js, debug=self.debug)
|
||||||
debug=self.debug)
|
|
||||||
for name in names:
|
for name in names:
|
||||||
cmd_dict[name] = cmd
|
cmd_dict[name] = cmd
|
||||||
return func
|
return func
|
||||||
@ -209,7 +209,7 @@ class register: # pylint: disable=invalid-name
|
|||||||
# we assume count always has a default (and it should!)
|
# we assume count always has a default (and it should!)
|
||||||
if self.nargs is not None:
|
if self.nargs is not None:
|
||||||
# If nargs is overriden, use that.
|
# If nargs is overriden, use that.
|
||||||
if isinstance(self.nargs, Iterable):
|
if isinstance(self.nargs, collections.Iterable):
|
||||||
# Iterable (min, max)
|
# Iterable (min, max)
|
||||||
# pylint: disable=unpacking-non-sequence
|
# pylint: disable=unpacking-non-sequence
|
||||||
minargs, maxargs = self.nargs
|
minargs, maxargs = self.nargs
|
||||||
|
@ -28,18 +28,15 @@ import os
|
|||||||
import os.path
|
import os.path
|
||||||
import textwrap
|
import textwrap
|
||||||
import configparser
|
import configparser
|
||||||
from configparser import ExtendedInterpolation
|
import collections.abc
|
||||||
from collections.abc import MutableMapping
|
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, QObject, QCoreApplication
|
from PyQt5.QtCore import pyqtSignal, QObject, QCoreApplication
|
||||||
|
|
||||||
import qutebrowser.config.configdata as configdata
|
from qutebrowser.utils import log
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.config import configdata, iniparsers, conftypes
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.commands import utils as cmdutils
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
from qutebrowser.config.iniparsers import ReadConfigParser
|
from qutebrowser.utils import message
|
||||||
from qutebrowser.config.conftypes import ValidationError
|
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
|
||||||
from qutebrowser.utils.usertypes import Completion
|
from qutebrowser.utils.usertypes import Completion
|
||||||
|
|
||||||
|
|
||||||
@ -114,7 +111,7 @@ class ConfigManager(QObject):
|
|||||||
def __init__(self, configdir, fname, parent=None):
|
def __init__(self, configdir, fname, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.sections = configdata.DATA
|
self.sections = configdata.DATA
|
||||||
self._configparser = ReadConfigParser(configdir, fname)
|
self._configparser = iniparsers.ReadConfigParser(configdir, fname)
|
||||||
self._configfile = os.path.join(configdir, fname)
|
self._configfile = os.path.join(configdir, fname)
|
||||||
self._wrapper_args = {
|
self._wrapper_args = {
|
||||||
'width': 72,
|
'width': 72,
|
||||||
@ -124,7 +121,7 @@ class ConfigManager(QObject):
|
|||||||
}
|
}
|
||||||
self._configdir = configdir
|
self._configdir = configdir
|
||||||
self._fname = fname
|
self._fname = fname
|
||||||
self._interpolation = ExtendedInterpolation()
|
self._interpolation = configparser.ExtendedInterpolation()
|
||||||
self._proxies = {}
|
self._proxies = {}
|
||||||
for sectname in self.sections.keys():
|
for sectname in self.sections.keys():
|
||||||
self._proxies[sectname] = SectionProxy(self, sectname)
|
self._proxies[sectname] = SectionProxy(self, sectname)
|
||||||
@ -227,7 +224,7 @@ class ConfigManager(QObject):
|
|||||||
k = k.replace('<eq>', '=')
|
k = k.replace('<eq>', '=')
|
||||||
try:
|
try:
|
||||||
self.set('conf', sectname, k, v)
|
self.set('conf', sectname, k, v)
|
||||||
except ValidationError as e:
|
except conftypes.ValidationError as e:
|
||||||
e.section = sectname
|
e.section = sectname
|
||||||
e.option = k
|
e.option = k
|
||||||
raise
|
raise
|
||||||
@ -299,7 +296,8 @@ class ConfigManager(QObject):
|
|||||||
try:
|
try:
|
||||||
val = self.get(sectname, optname, transformed=False)
|
val = self.get(sectname, optname, transformed=False)
|
||||||
except (NoOptionError, NoSectionError) as e:
|
except (NoOptionError, NoSectionError) as e:
|
||||||
raise CommandError("get: {} - {}".format(e.__class__.__name__, e))
|
raise cmdexc.CommandError("get: {} - {}".format(
|
||||||
|
e.__class__.__name__, e))
|
||||||
else:
|
else:
|
||||||
message.info("{} {} = {}".format(sectname, optname, val),
|
message.info("{} {} = {}".format(sectname, optname, val),
|
||||||
immediately=True)
|
immediately=True)
|
||||||
@ -350,9 +348,10 @@ class ConfigManager(QObject):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.set('conf', sectname, optname, value)
|
self.set('conf', sectname, optname, value)
|
||||||
except (NoOptionError, NoSectionError, ValidationError,
|
except (NoOptionError, NoSectionError, conftypes.ValidationError,
|
||||||
ValueError) as e:
|
ValueError) as e:
|
||||||
raise CommandError("set: {} - {}".format(e.__class__.__name__, e))
|
raise cmdexc.CommandError("set: {} - {}".format(
|
||||||
|
e.__class__.__name__, e))
|
||||||
|
|
||||||
@cmdutils.register(name='set-temp', instance='config',
|
@cmdutils.register(name='set-temp', instance='config',
|
||||||
completion=[Completion.section, Completion.option,
|
completion=[Completion.section, Completion.option,
|
||||||
@ -371,8 +370,9 @@ class ConfigManager(QObject):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.set('temp', sectname, optname, value)
|
self.set('temp', sectname, optname, value)
|
||||||
except (NoOptionError, NoSectionError, ValidationError) as e:
|
except (NoOptionError, NoSectionError, conftypes.ValidationError) as e:
|
||||||
raise CommandError("set: {} - {}".format(e.__class__.__name__, e))
|
raise cmdexc.CommandError("set: {} - {}".format(
|
||||||
|
e.__class__.__name__, e))
|
||||||
|
|
||||||
def set(self, layer, sectname, optname, value):
|
def set(self, layer, sectname, optname, value):
|
||||||
"""Set an option.
|
"""Set an option.
|
||||||
@ -442,7 +442,7 @@ class ConfigManager(QObject):
|
|||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
class SectionProxy(MutableMapping):
|
class SectionProxy(collections.abc.MutableMapping):
|
||||||
|
|
||||||
"""A proxy for a single section from a config.
|
"""A proxy for a single section from a config.
|
||||||
|
|
||||||
|
@ -27,11 +27,11 @@ DATA: The config defaults, an OrderedDict of sections.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from collections import OrderedDict
|
import collections
|
||||||
|
|
||||||
|
from qutebrowser.config import conftypes as typ
|
||||||
|
from qutebrowser.config import sections as sect
|
||||||
from qutebrowser.config.value import SettingValue
|
from qutebrowser.config.value import SettingValue
|
||||||
import qutebrowser.config.conftypes as types
|
|
||||||
import qutebrowser.config.sections as sect
|
|
||||||
from qutebrowser.utils.qt import MAXVALS
|
from qutebrowser.utils.qt import MAXVALS
|
||||||
|
|
||||||
|
|
||||||
@ -165,57 +165,57 @@ SECTION_DESC = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DATA = OrderedDict([
|
DATA = collections.OrderedDict([
|
||||||
('general', sect.KeyValue(
|
('general', sect.KeyValue(
|
||||||
('ignore-case',
|
('ignore-case',
|
||||||
SettingValue(types.IgnoreCase(), 'smart'),
|
SettingValue(typ.IgnoreCase(), 'smart'),
|
||||||
"Whether to find text on a page case-insensitively."),
|
"Whether to find text on a page case-insensitively."),
|
||||||
|
|
||||||
('wrap-search',
|
('wrap-search',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to wrap finding text to the top when arriving at the end."),
|
"Whether to wrap finding text to the top when arriving at the end."),
|
||||||
|
|
||||||
('startpage',
|
('startpage',
|
||||||
SettingValue(types.List(), 'http://www.duckduckgo.com'),
|
SettingValue(typ.List(), 'http://www.duckduckgo.com'),
|
||||||
"The default page(s) to open at the start, separated by commas."),
|
"The default page(s) to open at the start, separated by commas."),
|
||||||
|
|
||||||
('auto-search',
|
('auto-search',
|
||||||
SettingValue(types.AutoSearch(), 'naive'),
|
SettingValue(typ.AutoSearch(), 'naive'),
|
||||||
"Whether to start a search when something else than a URL is "
|
"Whether to start a search when something else than a URL is "
|
||||||
"entered."),
|
"entered."),
|
||||||
|
|
||||||
('auto-save-config',
|
('auto-save-config',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to save the config automatically on quit."),
|
"Whether to save the config automatically on quit."),
|
||||||
|
|
||||||
('editor',
|
('editor',
|
||||||
SettingValue(types.ShellCommand(placeholder=True), 'gvim -f "{}"'),
|
SettingValue(typ.ShellCommand(placeholder=True), 'gvim -f "{}"'),
|
||||||
"The editor (and arguments) to use for the `open-editor` command.\n\n"
|
"The editor (and arguments) to use for the `open-editor` command.\n\n"
|
||||||
"Use `{}` for the filename. The value gets split like in a shell, so "
|
"Use `{}` for the filename. The value gets split like in a shell, so "
|
||||||
"you can use `\"` or `'` to quote arguments."),
|
"you can use `\"` or `'` to quote arguments."),
|
||||||
|
|
||||||
('editor-encoding',
|
('editor-encoding',
|
||||||
SettingValue(types.Encoding(), 'utf-8'),
|
SettingValue(typ.Encoding(), 'utf-8'),
|
||||||
"Encoding to use for editor."),
|
"Encoding to use for editor."),
|
||||||
|
|
||||||
('private-browsing',
|
('private-browsing',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Do not record visited pages in the history or store web page "
|
"Do not record visited pages in the history or store web page "
|
||||||
"icons."),
|
"icons."),
|
||||||
|
|
||||||
('developer-extras',
|
('developer-extras',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Enable extra tools for Web developers.\n\n"
|
"Enable extra tools for Web developers.\n\n"
|
||||||
"This needs to be enabled for `:inspector` to work and also adds an "
|
"This needs to be enabled for `:inspector` to work and also adds an "
|
||||||
"_Inspect_ entry to the context menu."),
|
"_Inspect_ entry to the context menu."),
|
||||||
|
|
||||||
('print-element-backgrounds',
|
('print-element-backgrounds',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether the background color and images are also drawn when the "
|
"Whether the background color and images are also drawn when the "
|
||||||
"page is printed."),
|
"page is printed."),
|
||||||
|
|
||||||
('xss-auditing',
|
('xss-auditing',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether load requests should be monitored for cross-site scripting "
|
"Whether load requests should be monitored for cross-site scripting "
|
||||||
"attempts.\n\n"
|
"attempts.\n\n"
|
||||||
"Suspicious scripts will be blocked and reported in the inspector's "
|
"Suspicious scripts will be blocked and reported in the inspector's "
|
||||||
@ -223,11 +223,11 @@ DATA = OrderedDict([
|
|||||||
"performance."),
|
"performance."),
|
||||||
|
|
||||||
('site-specific-quirks',
|
('site-specific-quirks',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Enable workarounds for broken sites."),
|
"Enable workarounds for broken sites."),
|
||||||
|
|
||||||
('default-encoding',
|
('default-encoding',
|
||||||
SettingValue(types.String(none_ok=True), ''),
|
SettingValue(typ.String(none_ok=True), ''),
|
||||||
"Default encoding to use for websites.\n\n"
|
"Default encoding to use for websites.\n\n"
|
||||||
"The encoding must be a string describing an encoding such as "
|
"The encoding must be a string describing an encoding such as "
|
||||||
'_utf-8_, _iso-8859-1_, etc. If left empty a default value will be '
|
'_utf-8_, _iso-8859-1_, etc. If left empty a default value will be '
|
||||||
@ -236,126 +236,125 @@ DATA = OrderedDict([
|
|||||||
|
|
||||||
('ui', sect.KeyValue(
|
('ui', sect.KeyValue(
|
||||||
('zoom-levels',
|
('zoom-levels',
|
||||||
SettingValue(types.PercList(minval=0),
|
SettingValue(typ.PercList(minval=0),
|
||||||
'25%,33%,50%,67%,75%,90%,100%,110%,125%,150%,175%,200%,'
|
'25%,33%,50%,67%,75%,90%,100%,110%,125%,150%,175%,200%,'
|
||||||
'250%,300%,400%,500%'),
|
'250%,300%,400%,500%'),
|
||||||
"The available zoom levels, separated by commas."),
|
"The available zoom levels, separated by commas."),
|
||||||
|
|
||||||
('default-zoom',
|
('default-zoom',
|
||||||
SettingValue(types.ZoomPerc(), '100%'),
|
SettingValue(typ.ZoomPerc(), '100%'),
|
||||||
"The default zoom level."),
|
"The default zoom level."),
|
||||||
|
|
||||||
('message-timeout',
|
('message-timeout',
|
||||||
SettingValue(types.Int(), '2000'),
|
SettingValue(typ.Int(), '2000'),
|
||||||
"Time (in ms) to show messages in the statusbar for."),
|
"Time (in ms) to show messages in the statusbar for."),
|
||||||
|
|
||||||
('confirm-quit',
|
('confirm-quit',
|
||||||
SettingValue(types.ConfirmQuit(), 'never'),
|
SettingValue(typ.ConfirmQuit(), 'never'),
|
||||||
"Whether to confirm quitting the application."),
|
"Whether to confirm quitting the application."),
|
||||||
|
|
||||||
('display-statusbar-messages',
|
('display-statusbar-messages',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether to display javascript statusbar messages."),
|
"Whether to display javascript statusbar messages."),
|
||||||
|
|
||||||
('zoom-text-only',
|
('zoom-text-only',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether the zoom factor on a frame applies only to the text or to "
|
"Whether the zoom factor on a frame applies only to the text or to "
|
||||||
"all content."),
|
"all content."),
|
||||||
|
|
||||||
('frame-flattening',
|
('frame-flattening',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether to expand each subframe to its contents.\n\n"
|
"Whether to expand each subframe to its contents.\n\n"
|
||||||
"This will flatten all the frames to become one scrollable page."),
|
"This will flatten all the frames to become one scrollable page."),
|
||||||
|
|
||||||
('user-stylesheet',
|
('user-stylesheet',
|
||||||
SettingValue(types.WebSettingsFile(), ''),
|
SettingValue(typ.WebSettingsFile(), ''),
|
||||||
"User stylesheet to use."),
|
"User stylesheet to use."),
|
||||||
|
|
||||||
('css-media-type',
|
('css-media-type',
|
||||||
SettingValue(types.String(none_ok=True), ''),
|
SettingValue(typ.String(none_ok=True), ''),
|
||||||
"Set the CSS media type."),
|
"Set the CSS media type."),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('network', sect.KeyValue(
|
('network', sect.KeyValue(
|
||||||
('do-not-track',
|
('do-not-track',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Value to send in the `DNT` header."),
|
"Value to send in the `DNT` header."),
|
||||||
|
|
||||||
('accept-language',
|
('accept-language',
|
||||||
SettingValue(types.String(none_ok=True), 'en-US,en'),
|
SettingValue(typ.String(none_ok=True), 'en-US,en'),
|
||||||
"Value to send in the `accept-language` header."),
|
"Value to send in the `accept-language` header."),
|
||||||
|
|
||||||
('user-agent',
|
('user-agent',
|
||||||
SettingValue(types.String(none_ok=True), ''),
|
SettingValue(typ.String(none_ok=True), ''),
|
||||||
"User agent to send. Empty to send the default."),
|
"User agent to send. Empty to send the default."),
|
||||||
|
|
||||||
('proxy',
|
('proxy',
|
||||||
SettingValue(types.Proxy(), 'system'),
|
SettingValue(typ.Proxy(), 'system'),
|
||||||
"The proxy to use.\n\n"
|
"The proxy to use.\n\n"
|
||||||
"In addition to the listed values, you can use a `socks://...` or "
|
"In addition to the listed values, you can use a `socks://...` or "
|
||||||
"`http://...` URL."),
|
"`http://...` URL."),
|
||||||
|
|
||||||
('ssl-strict',
|
('ssl-strict',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to validate SSL handshakes."),
|
"Whether to validate SSL handshakes."),
|
||||||
|
|
||||||
('dns-prefetch',
|
('dns-prefetch',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to try to pre-fetch DNS entries to speed up browsing."),
|
"Whether to try to pre-fetch DNS entries to speed up browsing."),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('completion', sect.KeyValue(
|
('completion', sect.KeyValue(
|
||||||
('show',
|
('show',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to show the autocompletion window."),
|
"Whether to show the autocompletion window."),
|
||||||
|
|
||||||
('height',
|
('height',
|
||||||
SettingValue(types.PercOrInt(minperc=0, maxperc=100, minint=1),
|
SettingValue(typ.PercOrInt(minperc=0, maxperc=100, minint=1), '50%'),
|
||||||
'50%'),
|
|
||||||
"The height of the completion, in px or as percentage of the "
|
"The height of the completion, in px or as percentage of the "
|
||||||
"window."),
|
"window."),
|
||||||
|
|
||||||
('history-length',
|
('history-length',
|
||||||
SettingValue(types.Int(minval=-1), '100'),
|
SettingValue(typ.Int(minval=-1), '100'),
|
||||||
"How many commands to save in the history.\n\n"
|
"How many commands to save in the history.\n\n"
|
||||||
"0: no history / -1: unlimited"),
|
"0: no history / -1: unlimited"),
|
||||||
|
|
||||||
('quick-complete',
|
('quick-complete',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to move on to the next part when there's only one possible "
|
"Whether to move on to the next part when there's only one possible "
|
||||||
"completion left."),
|
"completion left."),
|
||||||
|
|
||||||
('shrink',
|
('shrink',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether to shrink the completion to be smaller than the configured "
|
"Whether to shrink the completion to be smaller than the configured "
|
||||||
"size if there are no scrollbars."),
|
"size if there are no scrollbars."),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('input', sect.KeyValue(
|
('input', sect.KeyValue(
|
||||||
('timeout',
|
('timeout',
|
||||||
SettingValue(types.Int(minval=0, maxval=MAXVALS['int']), '500'),
|
SettingValue(typ.Int(minval=0, maxval=MAXVALS['int']), '500'),
|
||||||
"Timeout for ambiguous keybindings."),
|
"Timeout for ambiguous keybindings."),
|
||||||
|
|
||||||
('insert-mode-on-plugins',
|
('insert-mode-on-plugins',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether to switch to insert mode when clicking flash and other "
|
"Whether to switch to insert mode when clicking flash and other "
|
||||||
"plugins."),
|
"plugins."),
|
||||||
|
|
||||||
('auto-leave-insert-mode',
|
('auto-leave-insert-mode',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to leave insert mode if a non-editable element is clicked."),
|
"Whether to leave insert mode if a non-editable element is clicked."),
|
||||||
|
|
||||||
('auto-insert-mode',
|
('auto-insert-mode',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether to automatically enter insert mode if an editable element "
|
"Whether to automatically enter insert mode if an editable element "
|
||||||
"is focused after page load."),
|
"is focused after page load."),
|
||||||
|
|
||||||
('forward-unbound-keys',
|
('forward-unbound-keys',
|
||||||
SettingValue(types.ForwardUnboundKeys(), 'auto'),
|
SettingValue(typ.ForwardUnboundKeys(), 'auto'),
|
||||||
"Whether to forward unbound keys to the webview in normal mode."),
|
"Whether to forward unbound keys to the webview in normal mode."),
|
||||||
|
|
||||||
('spatial-navigation',
|
('spatial-navigation',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Enables or disables the Spatial Navigation feature\n\n"
|
"Enables or disables the Spatial Navigation feature\n\n"
|
||||||
"Spatial navigation consists in the ability to navigate between "
|
"Spatial navigation consists in the ability to navigate between "
|
||||||
"focusable elements in a Web page, such as hyperlinks and form "
|
"focusable elements in a Web page, such as hyperlinks and form "
|
||||||
@ -365,76 +364,74 @@ DATA = OrderedDict([
|
|||||||
"right and which element he probably wants."),
|
"right and which element he probably wants."),
|
||||||
|
|
||||||
('links-included-in-focus-chain',
|
('links-included-in-focus-chain',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether hyperlinks should be included in the keyboard focus "
|
"Whether hyperlinks should be included in the keyboard focus chain."),
|
||||||
"chain."),
|
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('tabs', sect.KeyValue(
|
('tabs', sect.KeyValue(
|
||||||
('background-tabs',
|
('background-tabs',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether to open new tabs (middleclick/ctrl+click) in background."),
|
"Whether to open new tabs (middleclick/ctrl+click) in background."),
|
||||||
|
|
||||||
('select-on-remove',
|
('select-on-remove',
|
||||||
SettingValue(types.SelectOnRemove(), 'right'),
|
SettingValue(typ.SelectOnRemove(), 'right'),
|
||||||
"Which tab to select when the focused tab is removed."),
|
"Which tab to select when the focused tab is removed."),
|
||||||
|
|
||||||
('new-tab-position',
|
('new-tab-position',
|
||||||
SettingValue(types.NewTabPosition(), 'right'),
|
SettingValue(typ.NewTabPosition(), 'right'),
|
||||||
"How new tabs are positioned."),
|
"How new tabs are positioned."),
|
||||||
|
|
||||||
('new-tab-position-explicit',
|
('new-tab-position-explicit',
|
||||||
SettingValue(types.NewTabPosition(), 'last'),
|
SettingValue(typ.NewTabPosition(), 'last'),
|
||||||
"How new tabs opened explicitely are positioned."),
|
"How new tabs opened explicitely are positioned."),
|
||||||
|
|
||||||
('last-close',
|
('last-close',
|
||||||
SettingValue(types.LastClose(), 'ignore'),
|
SettingValue(typ.LastClose(), 'ignore'),
|
||||||
"Behaviour when the last tab is closed."),
|
"Behaviour when the last tab is closed."),
|
||||||
|
|
||||||
('wrap',
|
('wrap',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to wrap when changing tabs."),
|
"Whether to wrap when changing tabs."),
|
||||||
|
|
||||||
('movable',
|
('movable',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether tabs should be movable."),
|
"Whether tabs should be movable."),
|
||||||
|
|
||||||
('close-mouse-button',
|
('close-mouse-button',
|
||||||
SettingValue(types.CloseButton(), 'middle'),
|
SettingValue(typ.CloseButton(), 'middle'),
|
||||||
"On which mouse button to close tabs."),
|
"On which mouse button to close tabs."),
|
||||||
|
|
||||||
('position',
|
('position',
|
||||||
SettingValue(types.Position(), 'north'),
|
SettingValue(typ.Position(), 'north'),
|
||||||
"The position of the tab bar."),
|
"The position of the tab bar."),
|
||||||
|
|
||||||
('show-favicons',
|
('show-favicons',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to show favicons in the tab bar."),
|
"Whether to show favicons in the tab bar."),
|
||||||
|
|
||||||
('width',
|
('width',
|
||||||
SettingValue(types.PercOrInt(minperc=0, maxperc=100, minint=1),
|
SettingValue(typ.PercOrInt(minperc=0, maxperc=100, minint=1), '20%'),
|
||||||
'20%'),
|
|
||||||
"The width of the tab bar if it's vertical, in px or as percentage "
|
"The width of the tab bar if it's vertical, in px or as percentage "
|
||||||
"of the window."),
|
"of the window."),
|
||||||
|
|
||||||
('indicator-width',
|
('indicator-width',
|
||||||
SettingValue(types.Int(minval=0), '3'),
|
SettingValue(typ.Int(minval=0), '3'),
|
||||||
"Width of the progress indicator (0 to disable)."),
|
"Width of the progress indicator (0 to disable)."),
|
||||||
|
|
||||||
('indicator-space',
|
('indicator-space',
|
||||||
SettingValue(types.Int(minval=0), '3'),
|
SettingValue(typ.Int(minval=0), '3'),
|
||||||
"Spacing between tab edge and indicator."),
|
"Spacing between tab edge and indicator."),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('storage', sect.KeyValue(
|
('storage', sect.KeyValue(
|
||||||
('download-directory',
|
('download-directory',
|
||||||
SettingValue(types.Directory(none_ok=True), ''),
|
SettingValue(typ.Directory(none_ok=True), ''),
|
||||||
"The directory to save downloads to. An empty value selects a "
|
"The directory to save downloads to. An empty value selects a "
|
||||||
"sensible os-specific default."),
|
"sensible os-specific default."),
|
||||||
|
|
||||||
('maximum-pages-in-cache',
|
('maximum-pages-in-cache',
|
||||||
SettingValue(types.Int(none_ok=True, minval=0, maxval=MAXVALS['int']),
|
SettingValue(
|
||||||
''),
|
typ.Int(none_ok=True, minval=0, maxval=MAXVALS['int']), ''),
|
||||||
"The maximum number of pages to hold in the memory page cache.\n\n"
|
"The maximum number of pages to hold in the memory page cache.\n\n"
|
||||||
"The Page Cache allows for a nicer user experience when navigating "
|
"The Page Cache allows for a nicer user experience when navigating "
|
||||||
"forth or back to pages in the forward/back history, by pausing and "
|
"forth or back to pages in the forward/back history, by pausing and "
|
||||||
@ -443,8 +440,8 @@ DATA = OrderedDict([
|
|||||||
"http://webkit.org/blog/427/webkit-page-cache-i-the-basics/"),
|
"http://webkit.org/blog/427/webkit-page-cache-i-the-basics/"),
|
||||||
|
|
||||||
('object-cache-capacities',
|
('object-cache-capacities',
|
||||||
SettingValue(types.WebKitBytesList(length=3, maxsize=MAXVALS['int']),
|
SettingValue(
|
||||||
''),
|
typ.WebKitBytesList(length=3, maxsize=MAXVALS['int']), ''),
|
||||||
"The capacities for the memory cache for dead objects such as "
|
"The capacities for the memory cache for dead objects such as "
|
||||||
"stylesheets or scripts. Syntax: cacheMinDeadCapacity, cacheMaxDead, "
|
"stylesheets or scripts. Syntax: cacheMinDeadCapacity, cacheMaxDead, "
|
||||||
"totalCapacity.\n\n"
|
"totalCapacity.\n\n"
|
||||||
@ -457,19 +454,19 @@ DATA = OrderedDict([
|
|||||||
"that the cache should consume *overall*."),
|
"that the cache should consume *overall*."),
|
||||||
|
|
||||||
('offline-storage-default-quota',
|
('offline-storage-default-quota',
|
||||||
SettingValue(types.WebKitBytes(maxsize=MAXVALS['int64']), ''),
|
SettingValue(typ.WebKitBytes(maxsize=MAXVALS['int64']), ''),
|
||||||
"Default quota for new offline storage databases."),
|
"Default quota for new offline storage databases."),
|
||||||
|
|
||||||
('offline-web-application-cache-quota',
|
('offline-web-application-cache-quota',
|
||||||
SettingValue(types.WebKitBytes(maxsize=MAXVALS['int64']), ''),
|
SettingValue(typ.WebKitBytes(maxsize=MAXVALS['int64']), ''),
|
||||||
"Quota for the offline web application cache."),
|
"Quota for the offline web application cache."),
|
||||||
|
|
||||||
('offline-storage-database',
|
('offline-storage-database',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether support for the HTML 5 offline storage feature is enabled."),
|
"Whether support for the HTML 5 offline storage feature is enabled."),
|
||||||
|
|
||||||
('offline-web-application-storage',
|
('offline-web-application-storage',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether support for the HTML 5 web application cache feature is "
|
"Whether support for the HTML 5 web application cache feature is "
|
||||||
"enabled.\n\n"
|
"enabled.\n\n"
|
||||||
"An application cache acts like an HTTP cache in some sense. For "
|
"An application cache acts like an HTTP cache in some sense. For "
|
||||||
@ -480,96 +477,96 @@ DATA = OrderedDict([
|
|||||||
"http://dev.w3.org/html5/spec/Overview.html#appcache"),
|
"http://dev.w3.org/html5/spec/Overview.html#appcache"),
|
||||||
|
|
||||||
('local-storage',
|
('local-storage',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether support for the HTML 5 local storage feature is enabled."),
|
"Whether support for the HTML 5 local storage feature is enabled."),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('permissions', sect.KeyValue(
|
('permissions', sect.KeyValue(
|
||||||
('allow-images',
|
('allow-images',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether images are automatically loaded in web pages."),
|
"Whether images are automatically loaded in web pages."),
|
||||||
|
|
||||||
('allow-javascript',
|
('allow-javascript',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Enables or disables the running of JavaScript programs."),
|
"Enables or disables the running of JavaScript programs."),
|
||||||
|
|
||||||
('allow-plugins',
|
('allow-plugins',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Enables or disables plugins in Web pages.\n\n"
|
"Enables or disables plugins in Web pages.\n\n"
|
||||||
'Qt plugins with a mimetype such as "application/x-qt-plugin" are '
|
'Qt plugins with a mimetype such as "application/x-qt-plugin" are '
|
||||||
"not affected by this setting."),
|
"not affected by this setting."),
|
||||||
|
|
||||||
#('allow-java',
|
#('allow-java',
|
||||||
# SettingValue(types.Bool(), 'true'),
|
# SettingValue(typ.Bool(), 'true'),
|
||||||
# "Enables or disables Java applets. Currently Java applets are "
|
# "Enables or disables Java applets. Currently Java applets are "
|
||||||
# "not supported"),
|
# "not supported"),
|
||||||
|
|
||||||
('javascript-can-open-windows',
|
('javascript-can-open-windows',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether JavaScript programs can open new windows."),
|
"Whether JavaScript programs can open new windows."),
|
||||||
|
|
||||||
('javascript-can-close-windows',
|
('javascript-can-close-windows',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether JavaScript programs can close windows."),
|
"Whether JavaScript programs can close windows."),
|
||||||
|
|
||||||
('javascript-can-access-clipboard',
|
('javascript-can-access-clipboard',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether JavaScript programs can read or write to the clipboard."),
|
"Whether JavaScript programs can read or write to the clipboard."),
|
||||||
|
|
||||||
('local-content-can-access-remote-urls',
|
('local-content-can-access-remote-urls',
|
||||||
SettingValue(types.Bool(), 'false'),
|
SettingValue(typ.Bool(), 'false'),
|
||||||
"Whether locally loaded documents are allowed to access remote "
|
"Whether locally loaded documents are allowed to access remote "
|
||||||
"urls."),
|
"urls."),
|
||||||
|
|
||||||
('local-content-can-access-file-urls',
|
('local-content-can-access-file-urls',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether locally loaded documents are allowed to access other local "
|
"Whether locally loaded documents are allowed to access other local "
|
||||||
"urls."),
|
"urls."),
|
||||||
|
|
||||||
('cookies-accept',
|
('cookies-accept',
|
||||||
SettingValue(types.AcceptCookies(), 'default'),
|
SettingValue(typ.AcceptCookies(), 'default'),
|
||||||
"Whether to accept cookies."),
|
"Whether to accept cookies."),
|
||||||
|
|
||||||
('cookies-store',
|
('cookies-store',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to store cookies."),
|
"Whether to store cookies."),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('hints', sect.KeyValue(
|
('hints', sect.KeyValue(
|
||||||
('border',
|
('border',
|
||||||
SettingValue(types.String(), '1px solid #E3BE23'),
|
SettingValue(typ.String(), '1px solid #E3BE23'),
|
||||||
"CSS border value for hints."),
|
"CSS border value for hints."),
|
||||||
|
|
||||||
('opacity',
|
('opacity',
|
||||||
SettingValue(types.Float(minval=0.0, maxval=1.0), '0.7'),
|
SettingValue(typ.Float(minval=0.0, maxval=1.0), '0.7'),
|
||||||
"Opacity for hints."),
|
"Opacity for hints."),
|
||||||
|
|
||||||
('mode',
|
('mode',
|
||||||
SettingValue(types.HintMode(), 'letter'),
|
SettingValue(typ.HintMode(), 'letter'),
|
||||||
"Mode to use for hints."),
|
"Mode to use for hints."),
|
||||||
|
|
||||||
('chars',
|
('chars',
|
||||||
SettingValue(types.String(minlen=2), 'asdfghjkl'),
|
SettingValue(typ.String(minlen=2), 'asdfghjkl'),
|
||||||
"Chars used for hint strings."),
|
"Chars used for hint strings."),
|
||||||
|
|
||||||
('auto-follow',
|
('auto-follow',
|
||||||
SettingValue(types.Bool(), 'true'),
|
SettingValue(typ.Bool(), 'true'),
|
||||||
"Whether to auto-follow a hint if there's only one left."),
|
"Whether to auto-follow a hint if there's only one left."),
|
||||||
|
|
||||||
('next-regexes',
|
('next-regexes',
|
||||||
SettingValue(types.RegexList(flags=re.IGNORECASE),
|
SettingValue(typ.RegexList(flags=re.IGNORECASE),
|
||||||
r'\bnext\b,\bmore\b,\bnewer\b,\b[>→≫]\b,\b(>>|»)\b'),
|
r'\bnext\b,\bmore\b,\bnewer\b,\b[>→≫]\b,\b(>>|»)\b'),
|
||||||
"A comma-separated list of regexes to use for 'next' links."),
|
"A comma-separated list of regexes to use for 'next' links."),
|
||||||
|
|
||||||
('prev-regexes',
|
('prev-regexes',
|
||||||
SettingValue(types.RegexList(flags=re.IGNORECASE),
|
SettingValue(typ.RegexList(flags=re.IGNORECASE),
|
||||||
r'\bprev(ious)?\b,\bback\b,\bolder\b,\b[<←≪]\b,'
|
r'\bprev(ious)?\b,\bback\b,\bolder\b,\b[<←≪]\b,'
|
||||||
r'\b(<<|«)\b'),
|
r'\b(<<|«)\b'),
|
||||||
"A comma-separated list of regexes to use for 'prev' links."),
|
"A comma-separated list of regexes to use for 'prev' links."),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('searchengines', sect.ValueList(
|
('searchengines', sect.ValueList(
|
||||||
types.SearchEngineName(), types.SearchEngineUrl(),
|
typ.SearchEngineName(), typ.SearchEngineUrl(),
|
||||||
('DEFAULT', '${duckduckgo}'),
|
('DEFAULT', '${duckduckgo}'),
|
||||||
('duckduckgo', 'https://duckduckgo.com/?q={}'),
|
('duckduckgo', 'https://duckduckgo.com/?q={}'),
|
||||||
('ddg', '${duckduckgo}'),
|
('ddg', '${duckduckgo}'),
|
||||||
@ -581,7 +578,7 @@ DATA = OrderedDict([
|
|||||||
)),
|
)),
|
||||||
|
|
||||||
('keybind', sect.ValueList(
|
('keybind', sect.ValueList(
|
||||||
types.KeyBindingName(), types.KeyBinding(),
|
typ.KeyBindingName(), typ.KeyBinding(),
|
||||||
('o', 'set-cmd-text ":open "'),
|
('o', 'set-cmd-text ":open "'),
|
||||||
('go', 'set-cmd-text :open {url}'),
|
('go', 'set-cmd-text :open {url}'),
|
||||||
('O', 'set-cmd-text ":open-tab "'),
|
('O', 'set-cmd-text ":open-tab "'),
|
||||||
@ -674,7 +671,7 @@ DATA = OrderedDict([
|
|||||||
)),
|
)),
|
||||||
|
|
||||||
('keybind.insert', sect.ValueList(
|
('keybind.insert', sect.ValueList(
|
||||||
types.KeyBindingName(), types.KeyBinding(),
|
typ.KeyBindingName(), typ.KeyBinding(),
|
||||||
('<Escape>', 'leave-mode'),
|
('<Escape>', 'leave-mode'),
|
||||||
('<Ctrl-N>', 'leave-mode'),
|
('<Ctrl-N>', 'leave-mode'),
|
||||||
('<Ctrl-E>', 'open-editor'),
|
('<Ctrl-E>', 'open-editor'),
|
||||||
@ -682,7 +679,7 @@ DATA = OrderedDict([
|
|||||||
)),
|
)),
|
||||||
|
|
||||||
('keybind.hint', sect.ValueList(
|
('keybind.hint', sect.ValueList(
|
||||||
types.KeyBindingName(), types.KeyBinding(),
|
typ.KeyBindingName(), typ.KeyBinding(),
|
||||||
('<Return>', 'follow-hint'),
|
('<Return>', 'follow-hint'),
|
||||||
('<Escape>', 'leave-mode'),
|
('<Escape>', 'leave-mode'),
|
||||||
('<Ctrl-N>', 'leave-mode'),
|
('<Ctrl-N>', 'leave-mode'),
|
||||||
@ -690,7 +687,7 @@ DATA = OrderedDict([
|
|||||||
)),
|
)),
|
||||||
|
|
||||||
('keybind.passthrough', sect.ValueList(
|
('keybind.passthrough', sect.ValueList(
|
||||||
types.KeyBindingName(), types.KeyBinding(),
|
typ.KeyBindingName(), typ.KeyBinding(),
|
||||||
('<Escape>', 'leave-mode'),
|
('<Escape>', 'leave-mode'),
|
||||||
('<Ctrl-[>', '${<Escape>}'),
|
('<Ctrl-[>', '${<Escape>}'),
|
||||||
)),
|
)),
|
||||||
@ -699,7 +696,7 @@ DATA = OrderedDict([
|
|||||||
# text field.
|
# text field.
|
||||||
|
|
||||||
('keybind.command', sect.ValueList(
|
('keybind.command', sect.ValueList(
|
||||||
types.KeyBindingName(), types.KeyBinding(),
|
typ.KeyBindingName(), typ.KeyBinding(),
|
||||||
('<Escape>', 'leave-mode'),
|
('<Escape>', 'leave-mode'),
|
||||||
('<Ctrl-P>', 'command-history-prev'),
|
('<Ctrl-P>', 'command-history-prev'),
|
||||||
('<Ctrl-N>', 'command-history-next'),
|
('<Ctrl-N>', 'command-history-next'),
|
||||||
@ -726,7 +723,7 @@ DATA = OrderedDict([
|
|||||||
)),
|
)),
|
||||||
|
|
||||||
('keybind.prompt', sect.ValueList(
|
('keybind.prompt', sect.ValueList(
|
||||||
types.KeyBindingName(), types.KeyBinding(),
|
typ.KeyBindingName(), typ.KeyBinding(),
|
||||||
('<Escape>', 'leave-mode'),
|
('<Escape>', 'leave-mode'),
|
||||||
('<Return>', 'prompt-accept'),
|
('<Return>', 'prompt-accept'),
|
||||||
('y', 'prompt-yes'),
|
('y', 'prompt-yes'),
|
||||||
@ -749,255 +746,255 @@ DATA = OrderedDict([
|
|||||||
)),
|
)),
|
||||||
|
|
||||||
('aliases', sect.ValueList(
|
('aliases', sect.ValueList(
|
||||||
types.String(forbidden=' '), types.Command(),
|
typ.String(forbidden=' '), typ.Command(),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('colors', sect.KeyValue(
|
('colors', sect.KeyValue(
|
||||||
('completion.fg',
|
('completion.fg',
|
||||||
SettingValue(types.QtColor(), 'white'),
|
SettingValue(typ.QtColor(), 'white'),
|
||||||
"Text color of the completion widget."),
|
"Text color of the completion widget."),
|
||||||
|
|
||||||
('completion.bg',
|
('completion.bg',
|
||||||
SettingValue(types.QssColor(), '#333333'),
|
SettingValue(typ.QssColor(), '#333333'),
|
||||||
"Background color of the completion widget."),
|
"Background color of the completion widget."),
|
||||||
|
|
||||||
('completion.item.bg',
|
('completion.item.bg',
|
||||||
SettingValue(types.QssColor(), '${completion.bg}'),
|
SettingValue(typ.QssColor(), '${completion.bg}'),
|
||||||
"Background color of completion widget items."),
|
"Background color of completion widget items."),
|
||||||
|
|
||||||
('completion.category.fg',
|
('completion.category.fg',
|
||||||
SettingValue(types.QtColor(), 'white'),
|
SettingValue(typ.QtColor(), 'white'),
|
||||||
"Foreground color of completion widget category headers."),
|
"Foreground color of completion widget category headers."),
|
||||||
|
|
||||||
('completion.category.bg',
|
('completion.category.bg',
|
||||||
SettingValue(types.QssColor(), 'qlineargradient(x1:0, y1:0, x2:0, '
|
SettingValue(typ.QssColor(), 'qlineargradient(x1:0, y1:0, x2:0, '
|
||||||
'y2:1, stop:0 #888888, stop:1 #505050)'),
|
'y2:1, stop:0 #888888, stop:1 #505050)'),
|
||||||
"Background color of the completion widget category headers."),
|
"Background color of the completion widget category headers."),
|
||||||
|
|
||||||
('completion.category.border.top',
|
('completion.category.border.top',
|
||||||
SettingValue(types.QssColor(), 'black'),
|
SettingValue(typ.QssColor(), 'black'),
|
||||||
"Top border color of the completion widget category headers."),
|
"Top border color of the completion widget category headers."),
|
||||||
|
|
||||||
('completion.category.border.bottom',
|
('completion.category.border.bottom',
|
||||||
SettingValue(types.QssColor(), '${completion.category.border.top}'),
|
SettingValue(typ.QssColor(), '${completion.category.border.top}'),
|
||||||
"Bottom border color of the completion widget category headers."),
|
"Bottom border color of the completion widget category headers."),
|
||||||
|
|
||||||
('completion.item.selected.fg',
|
('completion.item.selected.fg',
|
||||||
SettingValue(types.QtColor(), 'black'),
|
SettingValue(typ.QtColor(), 'black'),
|
||||||
"Foreground color of the selected completion item."),
|
"Foreground color of the selected completion item."),
|
||||||
|
|
||||||
('completion.item.selected.bg',
|
('completion.item.selected.bg',
|
||||||
SettingValue(types.QssColor(), '#e8c000'),
|
SettingValue(typ.QssColor(), '#e8c000'),
|
||||||
"Background color of the selected completion item."),
|
"Background color of the selected completion item."),
|
||||||
|
|
||||||
('completion.item.selected.border.top',
|
('completion.item.selected.border.top',
|
||||||
SettingValue(types.QssColor(), '#bbbb00'),
|
SettingValue(typ.QssColor(), '#bbbb00'),
|
||||||
"Top border color of the completion widget category headers."),
|
"Top border color of the completion widget category headers."),
|
||||||
|
|
||||||
('completion.item.selected.border.bottom',
|
('completion.item.selected.border.bottom',
|
||||||
SettingValue(types.QssColor(), '${completion.item.selected.border.'
|
SettingValue(typ.QssColor(), '${completion.item.selected.border.'
|
||||||
'top}'),
|
'top}'),
|
||||||
"Bottom border color of the selected completion item."),
|
"Bottom border color of the selected completion item."),
|
||||||
|
|
||||||
('completion.match.fg',
|
('completion.match.fg',
|
||||||
SettingValue(types.QssColor(), '#ff4444'),
|
SettingValue(typ.QssColor(), '#ff4444'),
|
||||||
"Foreground color of the matched text in the completion."),
|
"Foreground color of the matched text in the completion."),
|
||||||
|
|
||||||
('statusbar.bg',
|
('statusbar.bg',
|
||||||
SettingValue(types.QssColor(), 'black'),
|
SettingValue(typ.QssColor(), 'black'),
|
||||||
"Foreground color of the statusbar."),
|
"Foreground color of the statusbar."),
|
||||||
|
|
||||||
('statusbar.fg',
|
('statusbar.fg',
|
||||||
SettingValue(types.QssColor(), 'white'),
|
SettingValue(typ.QssColor(), 'white'),
|
||||||
"Foreground color of the statusbar."),
|
"Foreground color of the statusbar."),
|
||||||
|
|
||||||
('statusbar.bg.error',
|
('statusbar.bg.error',
|
||||||
SettingValue(types.QssColor(), 'red'),
|
SettingValue(typ.QssColor(), 'red'),
|
||||||
"Background color of the statusbar if there was an error."),
|
"Background color of the statusbar if there was an error."),
|
||||||
|
|
||||||
('statusbar.bg.prompt',
|
('statusbar.bg.prompt',
|
||||||
SettingValue(types.QssColor(), 'darkblue'),
|
SettingValue(typ.QssColor(), 'darkblue'),
|
||||||
"Background color of the statusbar if there is a prompt."),
|
"Background color of the statusbar if there is a prompt."),
|
||||||
|
|
||||||
('statusbar.bg.insert',
|
('statusbar.bg.insert',
|
||||||
SettingValue(types.QssColor(), 'darkgreen'),
|
SettingValue(typ.QssColor(), 'darkgreen'),
|
||||||
"Background color of the statusbar in insert mode."),
|
"Background color of the statusbar in insert mode."),
|
||||||
|
|
||||||
('statusbar.progress.bg',
|
('statusbar.progress.bg',
|
||||||
SettingValue(types.QssColor(), 'white'),
|
SettingValue(typ.QssColor(), 'white'),
|
||||||
"Background color of the progress bar."),
|
"Background color of the progress bar."),
|
||||||
|
|
||||||
('statusbar.url.fg',
|
('statusbar.url.fg',
|
||||||
SettingValue(types.QssColor(), '${statusbar.fg}'),
|
SettingValue(typ.QssColor(), '${statusbar.fg}'),
|
||||||
"Default foreground color of the URL in the statusbar."),
|
"Default foreground color of the URL in the statusbar."),
|
||||||
|
|
||||||
('statusbar.url.fg.success',
|
('statusbar.url.fg.success',
|
||||||
SettingValue(types.QssColor(), 'lime'),
|
SettingValue(typ.QssColor(), 'lime'),
|
||||||
"Foreground color of the URL in the statusbar on successful "
|
"Foreground color of the URL in the statusbar on successful "
|
||||||
"load."),
|
"load."),
|
||||||
|
|
||||||
('statusbar.url.fg.error',
|
('statusbar.url.fg.error',
|
||||||
SettingValue(types.QssColor(), 'orange'),
|
SettingValue(typ.QssColor(), 'orange'),
|
||||||
"Foreground color of the URL in the statusbar on error."),
|
"Foreground color of the URL in the statusbar on error."),
|
||||||
|
|
||||||
('statusbar.url.fg.warn',
|
('statusbar.url.fg.warn',
|
||||||
SettingValue(types.QssColor(), 'yellow'),
|
SettingValue(typ.QssColor(), 'yellow'),
|
||||||
"Foreground color of the URL in the statusbar when there's a "
|
"Foreground color of the URL in the statusbar when there's a "
|
||||||
"warning."),
|
"warning."),
|
||||||
|
|
||||||
('statusbar.url.fg.hover',
|
('statusbar.url.fg.hover',
|
||||||
SettingValue(types.QssColor(), 'aqua'),
|
SettingValue(typ.QssColor(), 'aqua'),
|
||||||
"Foreground color of the URL in the statusbar for hovered "
|
"Foreground color of the URL in the statusbar for hovered links."),
|
||||||
"links."),
|
|
||||||
|
|
||||||
('tab.fg',
|
('tab.fg',
|
||||||
SettingValue(types.QtColor(), 'white'),
|
SettingValue(typ.QtColor(), 'white'),
|
||||||
"Foreground color of tabs."),
|
"Foreground color of tabs."),
|
||||||
|
|
||||||
('tab.bg.odd',
|
('tab.bg.odd',
|
||||||
SettingValue(types.QtColor(), 'grey'),
|
SettingValue(typ.QtColor(), 'grey'),
|
||||||
"Background color of unselected odd tabs."),
|
"Background color of unselected odd tabs."),
|
||||||
|
|
||||||
('tab.bg.even',
|
('tab.bg.even',
|
||||||
SettingValue(types.QtColor(), 'darkgrey'),
|
SettingValue(typ.QtColor(), 'darkgrey'),
|
||||||
"Background color of unselected even tabs."),
|
"Background color of unselected even tabs."),
|
||||||
|
|
||||||
('tab.bg.selected',
|
('tab.bg.selected',
|
||||||
SettingValue(types.QtColor(), 'black'),
|
SettingValue(typ.QtColor(), 'black'),
|
||||||
"Background color of selected tabs."),
|
"Background color of selected tabs."),
|
||||||
|
|
||||||
('tab.bg.bar',
|
('tab.bg.bar',
|
||||||
SettingValue(types.QtColor(), '#555555'),
|
SettingValue(typ.QtColor(), '#555555'),
|
||||||
"Background color of the tabbar."),
|
"Background color of the tabbar."),
|
||||||
|
|
||||||
('tab.indicator.start',
|
('tab.indicator.start',
|
||||||
SettingValue(types.QtColor(), '#0000aa'),
|
SettingValue(typ.QtColor(), '#0000aa'),
|
||||||
"Color gradient start for the tab indicator."),
|
"Color gradient start for the tab indicator."),
|
||||||
|
|
||||||
('tab.indicator.stop',
|
('tab.indicator.stop',
|
||||||
SettingValue(types.QtColor(), '#00aa00'),
|
SettingValue(typ.QtColor(), '#00aa00'),
|
||||||
"Color gradient end for the tab indicator."),
|
"Color gradient end for the tab indicator."),
|
||||||
|
|
||||||
('tab.indicator.error',
|
('tab.indicator.error',
|
||||||
SettingValue(types.QtColor(), '#ff0000'),
|
SettingValue(typ.QtColor(), '#ff0000'),
|
||||||
"Color for the tab indicator on errors.."),
|
"Color for the tab indicator on errors.."),
|
||||||
|
|
||||||
('tab.indicator.system',
|
('tab.indicator.system',
|
||||||
SettingValue(types.ColorSystem(), 'rgb'),
|
SettingValue(typ.ColorSystem(), 'rgb'),
|
||||||
"Color gradient interpolation system for the tab indicator."),
|
"Color gradient interpolation system for the tab indicator."),
|
||||||
|
|
||||||
('tab.seperator',
|
('tab.seperator',
|
||||||
SettingValue(types.QssColor(), '#555555'),
|
SettingValue(typ.QssColor(), '#555555'),
|
||||||
"Color for the tab seperator."),
|
"Color for the tab seperator."),
|
||||||
|
|
||||||
('hints.fg',
|
('hints.fg',
|
||||||
SettingValue(types.CssColor(), 'black'),
|
SettingValue(typ.CssColor(), 'black'),
|
||||||
"Font color for hints."),
|
"Font color for hints."),
|
||||||
|
|
||||||
('hints.fg.match',
|
('hints.fg.match',
|
||||||
SettingValue(types.CssColor(), 'green'),
|
SettingValue(typ.CssColor(), 'green'),
|
||||||
"Font color for the matched part of hints."),
|
"Font color for the matched part of hints."),
|
||||||
|
|
||||||
('hints.bg',
|
('hints.bg',
|
||||||
SettingValue(types.CssColor(), '-webkit-gradient(linear, left top, '
|
SettingValue(typ.CssColor(), '-webkit-gradient(linear, left top, '
|
||||||
'left bottom, color-stop(0%,#FFF785), '
|
'left bottom, color-stop(0%,#FFF785), '
|
||||||
'color-stop(100%,#FFC542))'),
|
'color-stop(100%,#FFC542))'),
|
||||||
"Background color for hints."),
|
"Background color for hints."),
|
||||||
|
|
||||||
('downloads.fg',
|
('downloads.fg',
|
||||||
SettingValue(types.QtColor(), '#ffffff'),
|
SettingValue(typ.QtColor(), '#ffffff'),
|
||||||
"Foreground color for downloads."),
|
"Foreground color for downloads."),
|
||||||
|
|
||||||
('downloads.bg.bar',
|
('downloads.bg.bar',
|
||||||
SettingValue(types.QssColor(), 'black'),
|
SettingValue(typ.QssColor(), 'black'),
|
||||||
"Background color for the download bar."),
|
"Background color for the download bar."),
|
||||||
|
|
||||||
('downloads.bg.start',
|
('downloads.bg.start',
|
||||||
SettingValue(types.QtColor(), '#0000aa'),
|
SettingValue(typ.QtColor(), '#0000aa'),
|
||||||
"Color gradient start for downloads."),
|
"Color gradient start for downloads."),
|
||||||
|
|
||||||
('downloads.bg.stop',
|
('downloads.bg.stop',
|
||||||
SettingValue(types.QtColor(), '#00aa00'),
|
SettingValue(typ.QtColor(), '#00aa00'),
|
||||||
"Color gradient end for downloads."),
|
"Color gradient end for downloads."),
|
||||||
|
|
||||||
('downloads.bg.system',
|
('downloads.bg.system',
|
||||||
SettingValue(types.ColorSystem(), 'rgb'),
|
SettingValue(typ.ColorSystem(), 'rgb'),
|
||||||
"Color gradient interpolation system for downloads."),
|
"Color gradient interpolation system for downloads."),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
('fonts', sect.KeyValue(
|
('fonts', sect.KeyValue(
|
||||||
('_monospace',
|
('_monospace',
|
||||||
SettingValue(types.Font(), 'Terminus, Monospace, "DejaVu Sans Mono", '
|
SettingValue(typ.Font(), 'Terminus, Monospace, "DejaVu Sans Mono", '
|
||||||
'Consolas, Monaco, "Bitstream Vera Sans Mono", '
|
'Consolas, Monaco, "Bitstream Vera Sans Mono", '
|
||||||
'"Andale Mono", "Liberation Mono", "Courier New", '
|
'"Andale Mono", "Liberation Mono", "Courier New", '
|
||||||
'Courier, monospace, Fixed, Terminal'),
|
'Courier, monospace, Fixed, Terminal'),
|
||||||
"Default monospace fonts."),
|
"Default monospace fonts."),
|
||||||
|
|
||||||
('completion',
|
('completion',
|
||||||
SettingValue(types.Font(), '8pt ${_monospace}'),
|
SettingValue(typ.Font(), '8pt ${_monospace}'),
|
||||||
"Font used in the completion widget."),
|
"Font used in the completion widget."),
|
||||||
|
|
||||||
('tabbar',
|
('tabbar',
|
||||||
SettingValue(types.QtFont(), '8pt ${_monospace}'),
|
SettingValue(typ.QtFont(), '8pt ${_monospace}'),
|
||||||
"Font used in the tabbar."),
|
"Font used in the tabbar."),
|
||||||
|
|
||||||
('statusbar',
|
('statusbar',
|
||||||
SettingValue(types.Font(), '8pt ${_monospace}'),
|
SettingValue(typ.Font(), '8pt ${_monospace}'),
|
||||||
"Font used in the statusbar."),
|
"Font used in the statusbar."),
|
||||||
|
|
||||||
('downloads',
|
('downloads',
|
||||||
SettingValue(types.Font(), '8pt ${_monospace}'),
|
SettingValue(typ.Font(), '8pt ${_monospace}'),
|
||||||
"Font used for the downloadbar."),
|
"Font used for the downloadbar."),
|
||||||
|
|
||||||
('hints',
|
('hints',
|
||||||
SettingValue(types.Font(), 'bold 12px Monospace'),
|
SettingValue(typ.Font(), 'bold 12px Monospace'),
|
||||||
"Font used for the hints."),
|
"Font used for the hints."),
|
||||||
|
|
||||||
('debug-console',
|
('debug-console',
|
||||||
SettingValue(types.QtFont(), '8pt ${_monospace}'),
|
SettingValue(typ.QtFont(), '8pt ${_monospace}'),
|
||||||
"Font used for the debugging console."),
|
"Font used for the debugging console."),
|
||||||
|
|
||||||
('web-family-standard',
|
('web-family-standard',
|
||||||
SettingValue(types.String(none_ok=True), ''),
|
SettingValue(typ.String(none_ok=True), ''),
|
||||||
"Font family for standard fonts."),
|
"Font family for standard fonts."),
|
||||||
|
|
||||||
('web-family-fixed',
|
('web-family-fixed',
|
||||||
SettingValue(types.String(none_ok=True), ''),
|
SettingValue(typ.String(none_ok=True), ''),
|
||||||
"Font family for fixed fonts."),
|
"Font family for fixed fonts."),
|
||||||
|
|
||||||
('web-family-serif',
|
('web-family-serif',
|
||||||
SettingValue(types.String(none_ok=True), ''),
|
SettingValue(typ.String(none_ok=True), ''),
|
||||||
"Font family for serif fonts."),
|
"Font family for serif fonts."),
|
||||||
|
|
||||||
('web-family-sans-serif',
|
('web-family-sans-serif',
|
||||||
SettingValue(types.String(none_ok=True), ''),
|
SettingValue(typ.String(none_ok=True), ''),
|
||||||
"Font family for sans-serif fonts."),
|
"Font family for sans-serif fonts."),
|
||||||
|
|
||||||
('web-family-cursive',
|
('web-family-cursive',
|
||||||
SettingValue(types.String(none_ok=True), ''),
|
SettingValue(typ.String(none_ok=True), ''),
|
||||||
"Font family for cursive fonts."),
|
"Font family for cursive fonts."),
|
||||||
|
|
||||||
('web-family-fantasy',
|
('web-family-fantasy',
|
||||||
SettingValue(types.String(none_ok=True), ''),
|
SettingValue(typ.String(none_ok=True), ''),
|
||||||
"Font family for fantasy fonts."),
|
"Font family for fantasy fonts."),
|
||||||
|
|
||||||
('web-size-minimum',
|
('web-size-minimum',
|
||||||
SettingValue(types.Int(none_ok=True, minval=1, maxval=MAXVALS['int']),
|
SettingValue(
|
||||||
''),
|
typ.Int(none_ok=True, minval=1, maxval=MAXVALS['int']), ''),
|
||||||
"The hard minimum font size."),
|
"The hard minimum font size."),
|
||||||
|
|
||||||
('web-size-minimum-logical',
|
('web-size-minimum-logical',
|
||||||
SettingValue(types.Int(none_ok=True, minval=1, maxval=MAXVALS['int']),
|
SettingValue(
|
||||||
''),
|
typ.Int(none_ok=True, minval=1, maxval=MAXVALS['int']), ''),
|
||||||
"The minimum logical font size that is applied when zooming out."),
|
"The minimum logical font size that is applied when zooming out."),
|
||||||
|
|
||||||
('web-size-default',
|
('web-size-default',
|
||||||
SettingValue(types.Int(none_ok=True, minval=1, maxval=MAXVALS['int']),
|
SettingValue(
|
||||||
''), "The default font size for regular text."),
|
typ.Int(none_ok=True, minval=1, maxval=MAXVALS['int']), ''),
|
||||||
|
"The default font size for regular text."),
|
||||||
|
|
||||||
('web-size-default-fixed',
|
('web-size-default-fixed',
|
||||||
SettingValue(types.Int(none_ok=True, minval=1, maxval=MAXVALS['int']),
|
SettingValue(
|
||||||
''),
|
typ.Int(none_ok=True, minval=1, maxval=MAXVALS['int']), ''),
|
||||||
"The default font size for fixed-pitch text."),
|
"The default font size for fixed-pitch text."),
|
||||||
)),
|
)),
|
||||||
])
|
])
|
||||||
|
@ -23,13 +23,13 @@ import re
|
|||||||
import shlex
|
import shlex
|
||||||
import codecs
|
import codecs
|
||||||
import os.path
|
import os.path
|
||||||
from sre_constants import error as RegexError
|
import sre_constants
|
||||||
|
|
||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QUrl
|
||||||
from PyQt5.QtGui import QColor, QFont
|
from PyQt5.QtGui import QColor, QFont
|
||||||
from PyQt5.QtNetwork import QNetworkProxy
|
from PyQt5.QtNetwork import QNetworkProxy
|
||||||
|
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import utils as cmdutils
|
||||||
|
|
||||||
|
|
||||||
SYSTEM_PROXY = object() # Return value for Proxy type
|
SYSTEM_PROXY = object() # Return value for Proxy type
|
||||||
@ -734,7 +734,7 @@ class Regex(BaseType):
|
|||||||
raise ValidationError(value, "may not be empty!")
|
raise ValidationError(value, "may not be empty!")
|
||||||
try:
|
try:
|
||||||
re.compile(value, self.flags)
|
re.compile(value, self.flags)
|
||||||
except RegexError as e:
|
except sre_constants.error as e:
|
||||||
raise ValidationError(value, "must be a valid regex - " + str(e))
|
raise ValidationError(value, "must be a valid regex - " + str(e))
|
||||||
|
|
||||||
def transform(self, value):
|
def transform(self, value):
|
||||||
@ -762,7 +762,7 @@ class RegexList(List):
|
|||||||
def validate(self, value):
|
def validate(self, value):
|
||||||
try:
|
try:
|
||||||
vals = self.transform(value)
|
vals = self.transform(value)
|
||||||
except RegexError as e:
|
except sre_constants.error as e:
|
||||||
raise ValidationError(value, "must be a list valid regexes - " +
|
raise ValidationError(value, "must be a list valid regexes - " +
|
||||||
str(e))
|
str(e))
|
||||||
if not self.none_ok and None in vals:
|
if not self.none_ok and None in vals:
|
||||||
|
@ -21,12 +21,12 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
from configparser import ConfigParser
|
import configparser
|
||||||
|
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.utils import log
|
||||||
|
|
||||||
|
|
||||||
class ReadConfigParser(ConfigParser):
|
class ReadConfigParser(configparser.ConfigParser):
|
||||||
|
|
||||||
"""Our own ConfigParser subclass to read the main config.
|
"""Our own ConfigParser subclass to read the main config.
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import os.path
|
|||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot
|
from PyQt5.QtCore import pyqtSlot
|
||||||
|
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.utils import log
|
||||||
|
|
||||||
|
|
||||||
class LineConfigParser:
|
class LineConfigParser:
|
||||||
@ -82,7 +82,7 @@ class LineConfigParser:
|
|||||||
log.destroy.debug("No data to save.")
|
log.destroy.debug("No data to save.")
|
||||||
return
|
return
|
||||||
# We need to import this here because config needs LineConfigParser.
|
# We need to import this here because config needs LineConfigParser.
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
limit = -1 if self._limit is None else config.get(*self._limit)
|
limit = -1 if self._limit is None else config.get(*self._limit)
|
||||||
if limit == 0:
|
if limit == 0:
|
||||||
return
|
return
|
||||||
@ -98,7 +98,7 @@ class LineConfigParser:
|
|||||||
if self._limit is None:
|
if self._limit is None:
|
||||||
return
|
return
|
||||||
# We need to import this here because config needs LineConfigParser.
|
# We need to import this here because config needs LineConfigParser.
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
value = config.get(section, option)
|
value = config.get(section, option)
|
||||||
if (section, option) == self._limit and value == 0:
|
if (section, option) == self._limit and value == 0:
|
||||||
if os.path.exists(self._configfile):
|
if os.path.exists(self._configfile):
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
|
|
||||||
"""Setting sections used for qutebrowser."""
|
"""Setting sections used for qutebrowser."""
|
||||||
|
|
||||||
from collections import OrderedDict, ChainMap
|
import collections
|
||||||
|
|
||||||
from qutebrowser.config.value import SettingValue
|
from qutebrowser.config import value as confvalue
|
||||||
|
|
||||||
|
|
||||||
class Section:
|
class Section:
|
||||||
@ -108,7 +108,7 @@ class KeyValue(Section):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
if not defaults:
|
if not defaults:
|
||||||
return
|
return
|
||||||
self.values = OrderedDict()
|
self.values = collections.OrderedDict()
|
||||||
for (k, v, desc) in defaults:
|
for (k, v, desc) in defaults:
|
||||||
assert k not in self.values, k
|
assert k not in self.values, k
|
||||||
self.values[k] = v
|
self.values[k] = v
|
||||||
@ -160,17 +160,17 @@ class ValueList(Section):
|
|||||||
self._ordered_value_cache = None
|
self._ordered_value_cache = None
|
||||||
self.keytype = keytype
|
self.keytype = keytype
|
||||||
self.valtype = valtype
|
self.valtype = valtype
|
||||||
self.layers = OrderedDict([
|
self.layers = collections.OrderedDict([
|
||||||
('default', OrderedDict()),
|
('default', collections.OrderedDict()),
|
||||||
('conf', OrderedDict()),
|
('conf', collections.OrderedDict()),
|
||||||
('temp', OrderedDict()),
|
('temp', collections.OrderedDict()),
|
||||||
])
|
])
|
||||||
defaultlayer = self.layers['default']
|
defaultlayer = self.layers['default']
|
||||||
for key, value in defaults:
|
for key, value in defaults:
|
||||||
assert key not in defaultlayer, key
|
assert key not in defaultlayer, key
|
||||||
defaultlayer[key] = SettingValue(valtype, value)
|
defaultlayer[key] = confvalue.SettingValue(valtype, value)
|
||||||
self.values = ChainMap(self.layers['temp'], self.layers['conf'],
|
self.values = collections.ChainMap(
|
||||||
self.layers['default'])
|
self.layers['temp'], self.layers['conf'], self.layers['default'])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ordered_values(self):
|
def ordered_values(self):
|
||||||
@ -180,7 +180,7 @@ class ValueList(Section):
|
|||||||
iterating/items/etc. when order matters.
|
iterating/items/etc. when order matters.
|
||||||
"""
|
"""
|
||||||
if self._ordered_value_cache is None:
|
if self._ordered_value_cache is None:
|
||||||
self._ordered_value_cache = OrderedDict()
|
self._ordered_value_cache = collections.OrderedDict()
|
||||||
for layer in self.layers.values():
|
for layer in self.layers.values():
|
||||||
self._ordered_value_cache.update(layer)
|
self._ordered_value_cache.update(layer)
|
||||||
return self._ordered_value_cache
|
return self._ordered_value_cache
|
||||||
@ -190,14 +190,15 @@ class ValueList(Section):
|
|||||||
if key in self.layers[layer]:
|
if key in self.layers[layer]:
|
||||||
self.layers[layer][key].setv(layer, value, interpolated)
|
self.layers[layer][key].setv(layer, value, interpolated)
|
||||||
else:
|
else:
|
||||||
val = SettingValue(self.valtype)
|
val = confvalue.SettingValue(self.valtype)
|
||||||
val.setv(layer, value, interpolated)
|
val.setv(layer, value, interpolated)
|
||||||
self.layers[layer][key] = val
|
self.layers[layer][key] = val
|
||||||
self._ordered_value_cache = None
|
self._ordered_value_cache = None
|
||||||
|
|
||||||
def dump_userconfig(self):
|
def dump_userconfig(self):
|
||||||
changed = []
|
changed = []
|
||||||
mapping = ChainMap(self.layers['temp'], self.layers['conf'])
|
mapping = collections.ChainMap(
|
||||||
|
self.layers['temp'], self.layers['conf'])
|
||||||
for k, v in mapping.items():
|
for k, v in mapping.items():
|
||||||
try:
|
try:
|
||||||
if v.value != self.layers['default'][k].value:
|
if v.value != self.layers['default'][k].value:
|
||||||
|
@ -24,13 +24,13 @@ Module attributes:
|
|||||||
_fontdict: The global cached FontDict.
|
_fontdict: The global cached FontDict.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from functools import partial
|
import functools
|
||||||
|
|
||||||
from PyQt5.QtGui import QColor
|
from PyQt5.QtGui import QColor
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.log import style as logger
|
from qutebrowser.utils.log import style as logger
|
||||||
from qutebrowser.utils.misc import compact_text
|
|
||||||
|
|
||||||
|
|
||||||
_colordict = None
|
_colordict = None
|
||||||
@ -68,9 +68,10 @@ def set_register_stylesheet(obj):
|
|||||||
"""
|
"""
|
||||||
qss = get_stylesheet(obj.STYLESHEET)
|
qss = get_stylesheet(obj.STYLESHEET)
|
||||||
logger.debug("stylesheet for {}: {}".format(obj.__class__.__name__,
|
logger.debug("stylesheet for {}: {}".format(obj.__class__.__name__,
|
||||||
compact_text(qss)))
|
utils.compact_text(qss)))
|
||||||
obj.setStyleSheet(qss)
|
obj.setStyleSheet(qss)
|
||||||
config.instance().changed.connect(partial(_update_stylesheet, obj))
|
config.instance().changed.connect(
|
||||||
|
functools.partial(_update_stylesheet, obj))
|
||||||
|
|
||||||
|
|
||||||
def _update_stylesheet(obj, _section, _option):
|
def _update_stylesheet(obj, _section, _option):
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
"""A single value (with multiple layers possibly) in the config."""
|
"""A single value (with multiple layers possibly) in the config."""
|
||||||
|
|
||||||
from collections import OrderedDict
|
import collections
|
||||||
|
|
||||||
|
|
||||||
class SettingValue:
|
class SettingValue:
|
||||||
@ -43,7 +43,8 @@ class SettingValue:
|
|||||||
default: Raw value to set.
|
default: Raw value to set.
|
||||||
"""
|
"""
|
||||||
self.typ = typ
|
self.typ = typ
|
||||||
self._values = OrderedDict.fromkeys(['temp', 'conf', 'default'])
|
self._values = collections.OrderedDict.fromkeys(
|
||||||
|
['temp', 'conf', 'default'])
|
||||||
self._values['default'] = default
|
self._values['default'] = default
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -72,7 +73,7 @@ class SettingValue:
|
|||||||
startlayer: The first layer to include.
|
startlayer: The first layer to include.
|
||||||
"""
|
"""
|
||||||
idx = list(self._values.keys()).index(startlayer)
|
idx = list(self._values.keys()).index(startlayer)
|
||||||
d = OrderedDict(list(self._values.items())[idx:])
|
d = collections.OrderedDict(list(self._values.items())[idx:])
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def get_first_value(self, startlayer=None):
|
def get_first_value(self, startlayer=None):
|
||||||
|
@ -30,11 +30,11 @@ from PyQt5.QtCore import pyqtSlot
|
|||||||
from PyQt5.QtWebKit import QWebSettings
|
from PyQt5.QtWebKit import QWebSettings
|
||||||
from PyQt5.QtCore import QStandardPaths
|
from PyQt5.QtCore import QStandardPaths
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.utils.usertypes import enum
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.misc import get_standard_dir
|
from qutebrowser.utils import misc as utils
|
||||||
|
|
||||||
MapType = enum('MapType', 'attribute', 'setter', 'static_setter')
|
MapType = usertypes.enum('MapType', 'attribute', 'setter', 'static_setter')
|
||||||
|
|
||||||
|
|
||||||
MAPPINGS = {
|
MAPPINGS = {
|
||||||
@ -177,7 +177,7 @@ def _set_setting(typ, arg, value):
|
|||||||
def init():
|
def init():
|
||||||
"""Initialize the global QWebSettings."""
|
"""Initialize the global QWebSettings."""
|
||||||
global settings
|
global settings
|
||||||
cachedir = get_standard_dir(QStandardPaths.CacheLocation)
|
cachedir = utils.get_standard_dir(QStandardPaths.CacheLocation)
|
||||||
QWebSettings.enablePersistentStorage(cachedir)
|
QWebSettings.enablePersistentStorage(cachedir)
|
||||||
settings = QWebSettings.globalSettings()
|
settings = QWebSettings.globalSettings()
|
||||||
for sectname, section in MAPPINGS.items():
|
for sectname, section in MAPPINGS.items():
|
||||||
|
@ -21,14 +21,14 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
import string
|
import string
|
||||||
from functools import partial
|
import functools
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QObject
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QObject
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.utils.usertypes import enum, Timer
|
from qutebrowser.utils import usertypes
|
||||||
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.log import keyboard as logger
|
from qutebrowser.utils.log import keyboard as logger
|
||||||
from qutebrowser.utils.misc import keyevent_to_string, normalize_keystr
|
|
||||||
|
|
||||||
|
|
||||||
class BaseKeyParser(QObject):
|
class BaseKeyParser(QObject):
|
||||||
@ -71,8 +71,9 @@ class BaseKeyParser(QObject):
|
|||||||
keystring_updated = pyqtSignal(str)
|
keystring_updated = pyqtSignal(str)
|
||||||
do_log = True
|
do_log = True
|
||||||
|
|
||||||
Match = enum('Match', 'partial', 'definitive', 'ambiguous', 'none')
|
Match = usertypes.enum('Match', 'partial', 'definitive', 'ambiguous',
|
||||||
Type = enum('Type', 'chain', 'special')
|
'none')
|
||||||
|
Type = usertypes.enum('Type', 'chain', 'special')
|
||||||
|
|
||||||
def __init__(self, parent=None, supports_count=None,
|
def __init__(self, parent=None, supports_count=None,
|
||||||
supports_chains=False):
|
supports_chains=False):
|
||||||
@ -113,7 +114,7 @@ class BaseKeyParser(QObject):
|
|||||||
Return:
|
Return:
|
||||||
True if event has been handled, False otherwise.
|
True if event has been handled, False otherwise.
|
||||||
"""
|
"""
|
||||||
binding = keyevent_to_string(e)
|
binding = utils.keyevent_to_string(e)
|
||||||
if binding is None:
|
if binding is None:
|
||||||
self._debug_log("Ignoring only-modifier keyeevent.")
|
self._debug_log("Ignoring only-modifier keyeevent.")
|
||||||
return False
|
return False
|
||||||
@ -266,11 +267,11 @@ class BaseKeyParser(QObject):
|
|||||||
# execute in `time' ms
|
# execute in `time' ms
|
||||||
self._debug_log("Scheduling execution of {} in {}ms".format(
|
self._debug_log("Scheduling execution of {} in {}ms".format(
|
||||||
binding, time))
|
binding, time))
|
||||||
self._timer = Timer(self, 'ambigious_match')
|
self._timer = usertypes.Timer(self, 'ambigious_match')
|
||||||
self._timer.setSingleShot(True)
|
self._timer.setSingleShot(True)
|
||||||
self._timer.setInterval(time)
|
self._timer.setInterval(time)
|
||||||
self._timer.timeout.connect(partial(self.delayed_exec, binding,
|
self._timer.timeout.connect(
|
||||||
count))
|
functools.partial(self.delayed_exec, binding, count))
|
||||||
self._timer.start()
|
self._timer.start()
|
||||||
|
|
||||||
def delayed_exec(self, command, count):
|
def delayed_exec(self, command, count):
|
||||||
@ -329,7 +330,7 @@ class BaseKeyParser(QObject):
|
|||||||
if not cmd:
|
if not cmd:
|
||||||
continue
|
continue
|
||||||
elif key.startswith('<') and key.endswith('>'):
|
elif key.startswith('<') and key.endswith('>'):
|
||||||
keystr = normalize_keystr(key[1:-1])
|
keystr = utils.normalize_keystr(key[1:-1])
|
||||||
self.special_bindings[keystr] = cmd
|
self.special_bindings[keystr] = cmd
|
||||||
elif self._supports_chains:
|
elif self._supports_chains:
|
||||||
self.bindings[key] = cmd
|
self.bindings[key] = cmd
|
||||||
|
@ -20,10 +20,9 @@
|
|||||||
"""Advanced keyparsers."""
|
"""Advanced keyparsers."""
|
||||||
|
|
||||||
from qutebrowser.keyinput.basekeyparser import BaseKeyParser
|
from qutebrowser.keyinput.basekeyparser import BaseKeyParser
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.utils import message
|
||||||
|
from qutebrowser.commands import runners
|
||||||
from qutebrowser.commands.runners import CommandRunner
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
from qutebrowser.commands.exceptions import CommandMetaError, CommandError
|
|
||||||
|
|
||||||
|
|
||||||
class CommandKeyParser(BaseKeyParser):
|
class CommandKeyParser(BaseKeyParser):
|
||||||
@ -37,12 +36,12 @@ class CommandKeyParser(BaseKeyParser):
|
|||||||
def __init__(self, parent=None, supports_count=None,
|
def __init__(self, parent=None, supports_count=None,
|
||||||
supports_chains=False):
|
supports_chains=False):
|
||||||
super().__init__(parent, supports_count, supports_chains)
|
super().__init__(parent, supports_count, supports_chains)
|
||||||
self.commandrunner = CommandRunner()
|
self.commandrunner = runners.CommandRunner()
|
||||||
|
|
||||||
def execute(self, cmdstr, _keytype, count=None):
|
def execute(self, cmdstr, _keytype, count=None):
|
||||||
try:
|
try:
|
||||||
self.commandrunner.run(cmdstr, count)
|
self.commandrunner.run(cmdstr, count)
|
||||||
except (CommandMetaError, CommandError) as e:
|
except (cmdexc.CommandMetaError, cmdexc.CommandError) as e:
|
||||||
message.error(e, immediately=True)
|
message.error(e, immediately=True)
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,11 +27,11 @@ from PyQt5.QtGui import QWindow
|
|||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QEvent
|
||||||
from PyQt5.QtWidgets import QApplication
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import utils as cmdutils
|
||||||
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.log import modes as logger
|
from qutebrowser.utils.log import modes as logger
|
||||||
from qutebrowser.utils.usertypes import KeyMode
|
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
|
||||||
|
|
||||||
|
|
||||||
class ModeLockedError(Exception):
|
class ModeLockedError(Exception):
|
||||||
@ -96,8 +96,8 @@ class ModeManager(QObject):
|
|||||||
arg: The mode which has been left.
|
arg: The mode which has been left.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
entered = pyqtSignal(KeyMode)
|
entered = pyqtSignal(usertypes.KeyMode)
|
||||||
left = pyqtSignal(KeyMode)
|
left = pyqtSignal(usertypes.KeyMode)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@ -142,7 +142,7 @@ class ModeManager(QObject):
|
|||||||
True if event should be filtered, False otherwise.
|
True if event should be filtered, False otherwise.
|
||||||
"""
|
"""
|
||||||
handler = self._handlers[self.mode]
|
handler = self._handlers[self.mode]
|
||||||
if self.mode != KeyMode.insert:
|
if self.mode != usertypes.KeyMode.insert:
|
||||||
logger.debug("got keypress in mode {} - calling handler {}".format(
|
logger.debug("got keypress in mode {} - calling handler {}".format(
|
||||||
self.mode, handler.__qualname__))
|
self.mode, handler.__qualname__))
|
||||||
handled = handler(event) if handler is not None else False
|
handled = handler(event) if handler is not None else False
|
||||||
@ -161,7 +161,7 @@ class ModeManager(QObject):
|
|||||||
if not filter_this:
|
if not filter_this:
|
||||||
self._releaseevents_to_pass.append(event)
|
self._releaseevents_to_pass.append(event)
|
||||||
|
|
||||||
if self.mode != KeyMode.insert:
|
if self.mode != usertypes.KeyMode.insert:
|
||||||
logger.debug("handled: {}, forward-unbound-keys: {}, passthrough: "
|
logger.debug("handled: {}, forward-unbound-keys: {}, passthrough: "
|
||||||
"{}, is_non_alnum: {} --> filter: {}".format(
|
"{}, is_non_alnum: {} --> filter: {}".format(
|
||||||
handled, self._forward_unbound_keys,
|
handled, self._forward_unbound_keys,
|
||||||
@ -186,7 +186,7 @@ class ModeManager(QObject):
|
|||||||
filter_this = False
|
filter_this = False
|
||||||
else:
|
else:
|
||||||
filter_this = True
|
filter_this = True
|
||||||
if self.mode != KeyMode.insert:
|
if self.mode != usertypes.KeyMode.insert:
|
||||||
logger.debug("filter: {}".format(filter_this))
|
logger.debug("filter: {}".format(filter_this))
|
||||||
return filter_this
|
return filter_this
|
||||||
|
|
||||||
@ -199,7 +199,7 @@ class ModeManager(QObject):
|
|||||||
passthrough: Whether to pass keybindings in this mode through to
|
passthrough: Whether to pass keybindings in this mode through to
|
||||||
the widgets.
|
the widgets.
|
||||||
"""
|
"""
|
||||||
if not isinstance(mode, KeyMode):
|
if not isinstance(mode, usertypes.KeyMode):
|
||||||
raise TypeError("Mode {} is no KeyMode member!".format(mode))
|
raise TypeError("Mode {} is no KeyMode member!".format(mode))
|
||||||
self._handlers[mode] = handler
|
self._handlers[mode] = handler
|
||||||
if passthrough:
|
if passthrough:
|
||||||
@ -215,7 +215,7 @@ class ModeManager(QObject):
|
|||||||
Emit:
|
Emit:
|
||||||
entered: With the new mode name.
|
entered: With the new mode name.
|
||||||
"""
|
"""
|
||||||
if not isinstance(mode, KeyMode):
|
if not isinstance(mode, usertypes.KeyMode):
|
||||||
raise TypeError("Mode {} is no KeyMode member!".format(mode))
|
raise TypeError("Mode {} is no KeyMode member!".format(mode))
|
||||||
if self.locked:
|
if self.locked:
|
||||||
logger.debug("Not entering mode {} because mode is locked to "
|
logger.debug("Not entering mode {} because mode is locked to "
|
||||||
@ -241,9 +241,9 @@ class ModeManager(QObject):
|
|||||||
mode: The mode to enter.
|
mode: The mode to enter.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
m = KeyMode[mode]
|
m = usertypes.KeyMode[mode]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise CommandError("Mode {} does not exist!".format(mode))
|
raise cmdexc.CommandError("Mode {} does not exist!".format(mode))
|
||||||
self.enter(m, 'command')
|
self.enter(m, 'command')
|
||||||
|
|
||||||
def leave(self, mode, reason=None):
|
def leave(self, mode, reason=None):
|
||||||
@ -267,10 +267,10 @@ class ModeManager(QObject):
|
|||||||
self.left.emit(mode)
|
self.left.emit(mode)
|
||||||
|
|
||||||
@cmdutils.register(instance='modeman', name='leave-mode',
|
@cmdutils.register(instance='modeman', name='leave-mode',
|
||||||
not_modes=[KeyMode.normal], hide=True)
|
not_modes=[usertypes.KeyMode.normal], hide=True)
|
||||||
def leave_current_mode(self):
|
def leave_current_mode(self):
|
||||||
"""Leave the mode we're currently in."""
|
"""Leave the mode we're currently in."""
|
||||||
if self.mode == KeyMode.normal:
|
if self.mode == usertypes.KeyMode.normal:
|
||||||
raise ValueError("Can't leave normal mode!")
|
raise ValueError("Can't leave normal mode!")
|
||||||
self.leave(self.mode, 'leave current')
|
self.leave(self.mode, 'leave current')
|
||||||
|
|
||||||
|
@ -25,18 +25,18 @@ Module attributes:
|
|||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, Qt
|
from PyQt5.QtCore import pyqtSignal, Qt
|
||||||
|
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.utils import message
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.keyinput.keyparser import CommandKeyParser
|
from qutebrowser.keyinput import keyparser
|
||||||
from qutebrowser.utils.usertypes import enum
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.log import keyboard as logger
|
from qutebrowser.utils.log import keyboard as logger
|
||||||
|
|
||||||
|
|
||||||
STARTCHARS = ":/?"
|
STARTCHARS = ":/?"
|
||||||
LastPress = enum('LastPress', 'none', 'filtertext', 'keystring')
|
LastPress = usertypes.enum('LastPress', 'none', 'filtertext', 'keystring')
|
||||||
|
|
||||||
|
|
||||||
class NormalKeyParser(CommandKeyParser):
|
class NormalKeyParser(keyparser.CommandKeyParser):
|
||||||
|
|
||||||
"""KeyParser for normalmode with added STARTCHARS detection."""
|
"""KeyParser for normalmode with added STARTCHARS detection."""
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ class NormalKeyParser(CommandKeyParser):
|
|||||||
return super()._handle_single_key(e)
|
return super()._handle_single_key(e)
|
||||||
|
|
||||||
|
|
||||||
class PromptKeyParser(CommandKeyParser):
|
class PromptKeyParser(keyparser.CommandKeyParser):
|
||||||
|
|
||||||
"""KeyParser for yes/no prompts."""
|
"""KeyParser for yes/no prompts."""
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ class PromptKeyParser(CommandKeyParser):
|
|||||||
return '<{}>'.format(self.__class__.__name__)
|
return '<{}>'.format(self.__class__.__name__)
|
||||||
|
|
||||||
|
|
||||||
class HintKeyParser(CommandKeyParser):
|
class HintKeyParser(keyparser.CommandKeyParser):
|
||||||
|
|
||||||
"""KeyChainParser for hints.
|
"""KeyChainParser for hints.
|
||||||
|
|
||||||
|
@ -26,11 +26,11 @@ Module attributes:
|
|||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtGui import QStandardItemModel, QStandardItem
|
from PyQt5.QtGui import QStandardItemModel, QStandardItem
|
||||||
|
|
||||||
from qutebrowser.utils.usertypes import enum
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
from qutebrowser.utils import qt as qtutils
|
||||||
|
|
||||||
|
|
||||||
Role = enum('Role', 'marks', 'sort', start=Qt.UserRole, is_int=True)
|
Role = usertypes.enum('Role', 'marks', 'sort', start=Qt.UserRole, is_int=True)
|
||||||
|
|
||||||
|
|
||||||
class BaseCompletionModel(QStandardItemModel):
|
class BaseCompletionModel(QStandardItemModel):
|
||||||
@ -74,7 +74,7 @@ class BaseCompletionModel(QStandardItemModel):
|
|||||||
index: A QModelIndex of the item to mark.
|
index: A QModelIndex of the item to mark.
|
||||||
needle: The string to mark.
|
needle: The string to mark.
|
||||||
"""
|
"""
|
||||||
qt_ensure_valid(index)
|
qtutils.qt_ensure_valid(index)
|
||||||
haystack = self.data(index)
|
haystack = self.data(index)
|
||||||
marks = self._get_marks(needle, haystack)
|
marks = self._get_marks(needle, haystack)
|
||||||
ok = self.setData(index, marks, Role.marks)
|
ok = self.setData(index, marks, Role.marks)
|
||||||
@ -132,7 +132,7 @@ class BaseCompletionModel(QStandardItemModel):
|
|||||||
Return:
|
Return:
|
||||||
The item flags, or Qt.NoItemFlags on error.
|
The item flags, or Qt.NoItemFlags on error.
|
||||||
"""
|
"""
|
||||||
qt_ensure_valid(index)
|
qtutils.qt_ensure_valid(index)
|
||||||
if index.parent().isValid():
|
if index.parent().isValid():
|
||||||
# item
|
# item
|
||||||
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
|
return Qt.ItemIsEnabled | Qt.ItemIsSelectable
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot
|
from PyQt5.QtCore import pyqtSlot
|
||||||
|
|
||||||
from qutebrowser.utils.usertypes import NeighborList
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.log import misc as logger
|
from qutebrowser.utils.log import misc as logger
|
||||||
|
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ class History:
|
|||||||
items = self.history
|
items = self.history
|
||||||
if not items:
|
if not items:
|
||||||
raise HistoryEmptyError
|
raise HistoryEmptyError
|
||||||
self._tmphist = NeighborList(items)
|
self._tmphist = usertypes.NeighborList(items)
|
||||||
return self._tmphist.lastitem()
|
return self._tmphist.lastitem()
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
|
@ -21,15 +21,14 @@
|
|||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot, Qt, QCoreApplication
|
from PyQt5.QtCore import pyqtSlot, Qt, QCoreApplication
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config, configdata
|
||||||
import qutebrowser.config.configdata as configdata
|
from qutebrowser.models import basecompletion
|
||||||
from qutebrowser.models.basecompletion import BaseCompletionModel
|
from qutebrowser.commands import utils as cmdutils
|
||||||
from qutebrowser.commands.utils import cmd_dict
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.log import completion as logger
|
from qutebrowser.utils.log import completion as logger
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
|
||||||
|
|
||||||
|
|
||||||
class SettingSectionCompletionModel(BaseCompletionModel):
|
class SettingSectionCompletionModel(basecompletion.BaseCompletionModel):
|
||||||
|
|
||||||
"""A CompletionModel filled with settings sections."""
|
"""A CompletionModel filled with settings sections."""
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ class SettingSectionCompletionModel(BaseCompletionModel):
|
|||||||
self.new_item(cat, name, desc)
|
self.new_item(cat, name, desc)
|
||||||
|
|
||||||
|
|
||||||
class SettingOptionCompletionModel(BaseCompletionModel):
|
class SettingOptionCompletionModel(basecompletion.BaseCompletionModel):
|
||||||
|
|
||||||
"""A CompletionModel filled with settings and their descriptions.
|
"""A CompletionModel filled with settings and their descriptions.
|
||||||
|
|
||||||
@ -88,14 +87,14 @@ class SettingOptionCompletionModel(BaseCompletionModel):
|
|||||||
return
|
return
|
||||||
val = config.get(section, option, raw=True)
|
val = config.get(section, option, raw=True)
|
||||||
idx = item.index()
|
idx = item.index()
|
||||||
qt_ensure_valid(idx)
|
qtutils.qt_ensure_valid(idx)
|
||||||
ok = self.setData(idx, val, Qt.DisplayRole)
|
ok = self.setData(idx, val, Qt.DisplayRole)
|
||||||
if not ok:
|
if not ok:
|
||||||
raise ValueError("Setting data failed! (section: {}, option: {}, "
|
raise ValueError("Setting data failed! (section: {}, option: {}, "
|
||||||
"value: {})".format(section, option, val))
|
"value: {})".format(section, option, val))
|
||||||
|
|
||||||
|
|
||||||
class SettingValueCompletionModel(BaseCompletionModel):
|
class SettingValueCompletionModel(basecompletion.BaseCompletionModel):
|
||||||
|
|
||||||
"""A CompletionModel filled with setting values.
|
"""A CompletionModel filled with setting values.
|
||||||
|
|
||||||
@ -139,14 +138,14 @@ class SettingValueCompletionModel(BaseCompletionModel):
|
|||||||
if not value:
|
if not value:
|
||||||
value = '""'
|
value = '""'
|
||||||
idx = self.cur_item.index()
|
idx = self.cur_item.index()
|
||||||
qt_ensure_valid(idx)
|
qtutils.qt_ensure_valid(idx)
|
||||||
ok = self.setData(idx, value, Qt.DisplayRole)
|
ok = self.setData(idx, value, Qt.DisplayRole)
|
||||||
if not ok:
|
if not ok:
|
||||||
raise ValueError("Setting data failed! (section: {}, option: {}, "
|
raise ValueError("Setting data failed! (section: {}, option: {}, "
|
||||||
"value: {})".format(section, option, value))
|
"value: {})".format(section, option, value))
|
||||||
|
|
||||||
|
|
||||||
class CommandCompletionModel(BaseCompletionModel):
|
class CommandCompletionModel(basecompletion.BaseCompletionModel):
|
||||||
|
|
||||||
"""A CompletionModel filled with all commands and descriptions."""
|
"""A CompletionModel filled with all commands and descriptions."""
|
||||||
|
|
||||||
@ -154,9 +153,9 @@ class CommandCompletionModel(BaseCompletionModel):
|
|||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
assert cmd_dict
|
assert cmdutils.cmd_dict
|
||||||
cmdlist = []
|
cmdlist = []
|
||||||
for obj in set(cmd_dict.values()):
|
for obj in set(cmdutils.cmd_dict.values()):
|
||||||
if obj.hide or (obj.debug and not
|
if obj.hide or (obj.debug and not
|
||||||
QCoreApplication.instance().args.debug):
|
QCoreApplication.instance().args.debug):
|
||||||
pass
|
pass
|
||||||
|
@ -25,9 +25,9 @@ Contains:
|
|||||||
|
|
||||||
from PyQt5.QtCore import QSortFilterProxyModel, QModelIndex
|
from PyQt5.QtCore import QSortFilterProxyModel, QModelIndex
|
||||||
|
|
||||||
from qutebrowser.models.basecompletion import Role
|
from qutebrowser.models import basecompletion as completion
|
||||||
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.log import completion as logger
|
from qutebrowser.utils.log import completion as logger
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
|
||||||
|
|
||||||
|
|
||||||
class CompletionFilterModel(QSortFilterProxyModel):
|
class CompletionFilterModel(QSortFilterProxyModel):
|
||||||
@ -81,7 +81,7 @@ class CompletionFilterModel(QSortFilterProxyModel):
|
|||||||
count = 0
|
count = 0
|
||||||
for i in range(self.rowCount()):
|
for i in range(self.rowCount()):
|
||||||
cat = self.index(i, 0)
|
cat = self.index(i, 0)
|
||||||
qt_ensure_valid(cat)
|
qtutils.qt_ensure_valid(cat)
|
||||||
count += self.rowCount(cat)
|
count += self.rowCount(cat)
|
||||||
return count
|
return count
|
||||||
|
|
||||||
@ -89,10 +89,10 @@ class CompletionFilterModel(QSortFilterProxyModel):
|
|||||||
"""Return the first item in the model."""
|
"""Return the first item in the model."""
|
||||||
for i in range(self.rowCount()):
|
for i in range(self.rowCount()):
|
||||||
cat = self.index(i, 0)
|
cat = self.index(i, 0)
|
||||||
qt_ensure_valid(cat)
|
qtutils.qt_ensure_valid(cat)
|
||||||
if cat.model().hasChildren(cat):
|
if cat.model().hasChildren(cat):
|
||||||
index = self.index(0, 0, cat)
|
index = self.index(0, 0, cat)
|
||||||
qt_ensure_valid(index)
|
qtutils.qt_ensure_valid(index)
|
||||||
return index
|
return index
|
||||||
return QModelIndex()
|
return QModelIndex()
|
||||||
|
|
||||||
@ -100,10 +100,10 @@ class CompletionFilterModel(QSortFilterProxyModel):
|
|||||||
"""Return the last item in the model."""
|
"""Return the last item in the model."""
|
||||||
for i in range(self.rowCount() - 1, -1, -1):
|
for i in range(self.rowCount() - 1, -1, -1):
|
||||||
cat = self.index(i, 0)
|
cat = self.index(i, 0)
|
||||||
qt_ensure_valid(cat)
|
qtutils.qt_ensure_valid(cat)
|
||||||
if cat.model().hasChildren(cat):
|
if cat.model().hasChildren(cat):
|
||||||
index = self.index(self.rowCount(cat) - 1, 0, cat)
|
index = self.index(self.rowCount(cat) - 1, 0, cat)
|
||||||
qt_ensure_valid(index)
|
qtutils.qt_ensure_valid(index)
|
||||||
return index
|
return index
|
||||||
return QModelIndex()
|
return QModelIndex()
|
||||||
|
|
||||||
@ -111,12 +111,12 @@ class CompletionFilterModel(QSortFilterProxyModel):
|
|||||||
"""Mark the given text in all visible items."""
|
"""Mark the given text in all visible items."""
|
||||||
for i in range(self.rowCount()):
|
for i in range(self.rowCount()):
|
||||||
cat = self.index(i, 0)
|
cat = self.index(i, 0)
|
||||||
qt_ensure_valid(cat)
|
qtutils.qt_ensure_valid(cat)
|
||||||
for k in range(self.rowCount(cat)):
|
for k in range(self.rowCount(cat)):
|
||||||
index = self.index(k, 0, cat)
|
index = self.index(k, 0, cat)
|
||||||
qt_ensure_valid(index)
|
qtutils.qt_ensure_valid(index)
|
||||||
index = self.mapToSource(index)
|
index = self.mapToSource(index)
|
||||||
qt_ensure_valid(index)
|
qtutils.qt_ensure_valid(index)
|
||||||
self.srcmodel.mark_item(index, text)
|
self.srcmodel.mark_item(index, text)
|
||||||
|
|
||||||
def setSourceModel(self, model):
|
def setSourceModel(self, model):
|
||||||
@ -142,7 +142,7 @@ class CompletionFilterModel(QSortFilterProxyModel):
|
|||||||
if parent == QModelIndex():
|
if parent == QModelIndex():
|
||||||
return True
|
return True
|
||||||
idx = self.srcmodel.index(row, 0, parent)
|
idx = self.srcmodel.index(row, 0, parent)
|
||||||
qt_ensure_valid(idx)
|
qtutils.qt_ensure_valid(idx)
|
||||||
data = self.srcmodel.data(idx)
|
data = self.srcmodel.data(idx)
|
||||||
# TODO more sophisticated filtering
|
# TODO more sophisticated filtering
|
||||||
if not self.pattern:
|
if not self.pattern:
|
||||||
@ -162,11 +162,11 @@ class CompletionFilterModel(QSortFilterProxyModel):
|
|||||||
Return:
|
Return:
|
||||||
True if left < right, else False
|
True if left < right, else False
|
||||||
"""
|
"""
|
||||||
qt_ensure_valid(lindex)
|
qtutils.qt_ensure_valid(lindex)
|
||||||
qt_ensure_valid(rindex)
|
qtutils.qt_ensure_valid(rindex)
|
||||||
|
|
||||||
left_sort = self.srcmodel.data(lindex, role=Role.sort)
|
left_sort = self.srcmodel.data(lindex, role=completion.Role.sort)
|
||||||
right_sort = self.srcmodel.data(rindex, role=Role.sort)
|
right_sort = self.srcmodel.data(rindex, role=completion.Role.sort)
|
||||||
|
|
||||||
if left_sort is not None and right_sort is not None:
|
if left_sort is not None and right_sort is not None:
|
||||||
return left_sort < right_sort
|
return left_sort < right_sort
|
||||||
|
@ -23,12 +23,12 @@ from PyQt5.QtCore import (pyqtSlot, Qt, QVariant, QAbstractListModel,
|
|||||||
QModelIndex)
|
QModelIndex)
|
||||||
from PyQt5.QtWidgets import QApplication
|
from PyQt5.QtWidgets import QApplication
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.utils.usertypes import enum
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
from qutebrowser.utils import qt as qtutils
|
||||||
|
|
||||||
|
|
||||||
Role = enum('Role', 'item', start=Qt.UserRole, is_int=True)
|
Role = usertypes.enum('Role', 'item', start=Qt.UserRole, is_int=True)
|
||||||
|
|
||||||
|
|
||||||
class DownloadModel(QAbstractListModel):
|
class DownloadModel(QAbstractListModel):
|
||||||
@ -57,7 +57,7 @@ class DownloadModel(QAbstractListModel):
|
|||||||
def on_data_changed(self, idx):
|
def on_data_changed(self, idx):
|
||||||
"""Update view when DownloadManager data changed."""
|
"""Update view when DownloadManager data changed."""
|
||||||
model_idx = self.index(idx, 0)
|
model_idx = self.index(idx, 0)
|
||||||
qt_ensure_valid(model_idx)
|
qtutils.qt_ensure_valid(model_idx)
|
||||||
self.dataChanged.emit(model_idx, model_idx)
|
self.dataChanged.emit(model_idx, model_idx)
|
||||||
|
|
||||||
def last_index(self):
|
def last_index(self):
|
||||||
@ -79,7 +79,7 @@ class DownloadModel(QAbstractListModel):
|
|||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
"""Download data from DownloadManager."""
|
"""Download data from DownloadManager."""
|
||||||
qt_ensure_valid(index)
|
qtutils.qt_ensure_valid(index)
|
||||||
if index.parent().isValid() or index.column() != 0:
|
if index.parent().isValid() or index.column() != 0:
|
||||||
return QVariant()
|
return QVariant()
|
||||||
|
|
||||||
|
@ -29,12 +29,9 @@ except ImportError:
|
|||||||
else:
|
else:
|
||||||
SSL_AVAILABLE = QSslSocket.supportsSsl()
|
SSL_AVAILABLE = QSslSocket.supportsSsl()
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.utils import message, log, usertypes
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.network import qutescheme, schemehandler
|
||||||
from qutebrowser.network.qutescheme import QuteSchemeHandler
|
|
||||||
from qutebrowser.network.schemehandler import ErrorNetworkReply
|
|
||||||
from qutebrowser.utils.usertypes import PromptMode
|
|
||||||
|
|
||||||
|
|
||||||
class NetworkManager(QNetworkAccessManager):
|
class NetworkManager(QNetworkAccessManager):
|
||||||
@ -52,7 +49,7 @@ class NetworkManager(QNetworkAccessManager):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._requests = []
|
self._requests = []
|
||||||
self._scheme_handlers = {
|
self._scheme_handlers = {
|
||||||
'qute': QuteSchemeHandler(),
|
'qute': qutescheme.QuteSchemeHandler(),
|
||||||
}
|
}
|
||||||
cookiejar = QCoreApplication.instance().cookiejar
|
cookiejar = QCoreApplication.instance().cookiejar
|
||||||
parent = cookiejar.parent()
|
parent = cookiejar.parent()
|
||||||
@ -105,14 +102,14 @@ class NetworkManager(QNetworkAccessManager):
|
|||||||
def on_authentication_required(self, _reply, authenticator):
|
def on_authentication_required(self, _reply, authenticator):
|
||||||
"""Called when a website needs authentication."""
|
"""Called when a website needs authentication."""
|
||||||
answer = message.ask("Username ({}):".format(authenticator.realm()),
|
answer = message.ask("Username ({}):".format(authenticator.realm()),
|
||||||
mode=PromptMode.user_pwd)
|
mode=usertypes.PromptMode.user_pwd)
|
||||||
self._fill_authenticator(authenticator, answer)
|
self._fill_authenticator(authenticator, answer)
|
||||||
|
|
||||||
@pyqtSlot('QNetworkProxy', 'QAuthenticator')
|
@pyqtSlot('QNetworkProxy', 'QAuthenticator')
|
||||||
def on_proxy_authentication_required(self, _proxy, authenticator):
|
def on_proxy_authentication_required(self, _proxy, authenticator):
|
||||||
"""Called when a proxy needs authentication."""
|
"""Called when a proxy needs authentication."""
|
||||||
answer = message.ask("Proxy username ({}):".format(
|
answer = message.ask("Proxy username ({}):".format(
|
||||||
authenticator.realm()), mode=PromptMode.user_pwd)
|
authenticator.realm()), mode=usertypes.PromptMode.user_pwd)
|
||||||
self._fill_authenticator(authenticator, answer)
|
self._fill_authenticator(authenticator, answer)
|
||||||
|
|
||||||
def createRequest(self, op, req, outgoing_data):
|
def createRequest(self, op, req, outgoing_data):
|
||||||
@ -131,7 +128,7 @@ class NetworkManager(QNetworkAccessManager):
|
|||||||
"""
|
"""
|
||||||
scheme = req.url().scheme()
|
scheme = req.url().scheme()
|
||||||
if scheme == 'https' and not SSL_AVAILABLE:
|
if scheme == 'https' and not SSL_AVAILABLE:
|
||||||
return ErrorNetworkReply(
|
return schemehandler.ErrorNetworkReply(
|
||||||
req, "SSL is not supported by the installed Qt library!",
|
req, "SSL is not supported by the installed Qt library!",
|
||||||
QNetworkReply.ProtocolUnknownError)
|
QNetworkReply.ProtocolUnknownError)
|
||||||
elif scheme in self._scheme_handlers:
|
elif scheme in self._scheme_handlers:
|
||||||
|
@ -19,11 +19,11 @@
|
|||||||
|
|
||||||
"""Handling of proxies."""
|
"""Handling of proxies."""
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
|
||||||
from qutebrowser.config.conftypes import SYSTEM_PROXY
|
|
||||||
|
|
||||||
from PyQt5.QtNetwork import QNetworkProxyFactory
|
from PyQt5.QtNetwork import QNetworkProxyFactory
|
||||||
|
|
||||||
|
from qutebrowser.config import config, conftypes
|
||||||
|
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
"""Set the application wide proxy factory."""
|
"""Set the application wide proxy factory."""
|
||||||
@ -44,7 +44,7 @@ class ProxyFactory(QNetworkProxyFactory):
|
|||||||
A list of QNetworkProxy objects in order of preference.
|
A list of QNetworkProxy objects in order of preference.
|
||||||
"""
|
"""
|
||||||
proxy = config.get('network', 'proxy')
|
proxy = config.get('network', 'proxy')
|
||||||
if proxy is SYSTEM_PROXY:
|
if proxy is conftypes.SYSTEM_PROXY:
|
||||||
return QNetworkProxyFactory.systemProxyForQuery(query)
|
return QNetworkProxyFactory.systemProxyForQuery(query)
|
||||||
else:
|
else:
|
||||||
return [proxy]
|
return [proxy]
|
||||||
|
@ -29,12 +29,10 @@ import html as pyhtml
|
|||||||
from PyQt5.QtNetwork import QNetworkReply
|
from PyQt5.QtNetwork import QNetworkReply
|
||||||
|
|
||||||
import qutebrowser
|
import qutebrowser
|
||||||
import qutebrowser.utils.log as logutils
|
from qutebrowser.network import schemehandler
|
||||||
import qutebrowser.utils.version as version
|
from qutebrowser.utils import version
|
||||||
from qutebrowser.network.schemehandler import (SchemeHandler,
|
from qutebrowser.utils import log as logutils
|
||||||
SpecialNetworkReply,
|
from qutebrowser.utils import misc as utils
|
||||||
ErrorNetworkReply)
|
|
||||||
from qutebrowser.utils.misc import read_file
|
|
||||||
|
|
||||||
|
|
||||||
_HTML_TEMPLATE = """
|
_HTML_TEMPLATE = """
|
||||||
@ -73,7 +71,7 @@ def _get_html(title, snippet, head=None):
|
|||||||
return html
|
return html
|
||||||
|
|
||||||
|
|
||||||
class QuteSchemeHandler(SchemeHandler):
|
class QuteSchemeHandler(schemehandler.SchemeHandler):
|
||||||
|
|
||||||
"""Scheme handler for qute: URLs."""
|
"""Scheme handler for qute: URLs."""
|
||||||
|
|
||||||
@ -97,12 +95,13 @@ class QuteSchemeHandler(SchemeHandler):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
errorstr = "No handler found for {}!".format(
|
errorstr = "No handler found for {}!".format(
|
||||||
request.url().toDisplayString())
|
request.url().toDisplayString())
|
||||||
return ErrorNetworkReply(request, errorstr,
|
return schemehandler.ErrorNetworkReply(
|
||||||
QNetworkReply.ContentNotFoundError,
|
request, errorstr, QNetworkReply.ContentNotFoundError,
|
||||||
self.parent())
|
self.parent())
|
||||||
else:
|
else:
|
||||||
data = handler()
|
data = handler()
|
||||||
return SpecialNetworkReply(request, data, 'text/html', self.parent())
|
return schemehandler.SpecialNetworkReply(
|
||||||
|
request, data, 'text/html', self.parent())
|
||||||
|
|
||||||
|
|
||||||
class QuteHandlers:
|
class QuteHandlers:
|
||||||
@ -171,4 +170,4 @@ class QuteHandlers:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def gpl(cls):
|
def gpl(cls):
|
||||||
"""Handler for qute:gpl. Return HTML content as bytes."""
|
"""Handler for qute:gpl. Return HTML content as bytes."""
|
||||||
return read_file('html/COPYING.html').encode('ASCII')
|
return utils.read_file('html/COPYING.html').encode('ASCII')
|
||||||
|
@ -37,14 +37,14 @@ except ImportError:
|
|||||||
sys.exit(100)
|
sys.exit(100)
|
||||||
check_python_version()
|
check_python_version()
|
||||||
|
|
||||||
from argparse import ArgumentParser
|
import argparse
|
||||||
import qutebrowser.utils.earlyinit as earlyinit
|
from qutebrowser.utils import earlyinit
|
||||||
|
|
||||||
|
|
||||||
def get_argparser():
|
def get_argparser():
|
||||||
"""Get the argparse parser."""
|
"""Get the argparse parser."""
|
||||||
parser = ArgumentParser("usage: qutebrowser",
|
parser = argparse.ArgumentParser("usage: qutebrowser",
|
||||||
description=qutebrowser.__description__)
|
description=qutebrowser.__description__)
|
||||||
parser.add_argument('-c', '--confdir', help="Set config directory (empty "
|
parser.add_argument('-c', '--confdir', help="Set config directory (empty "
|
||||||
"for no config storage)")
|
"for no config storage)")
|
||||||
parser.add_argument('-V', '--version', help="Show version and quit.",
|
parser.add_argument('-V', '--version', help="Show version and quit.",
|
||||||
@ -103,7 +103,7 @@ def main():
|
|||||||
earlyinit.check_pyqt_core()
|
earlyinit.check_pyqt_core()
|
||||||
# We do this import late as we need to do the version checking first.
|
# We do this import late as we need to do the version checking first.
|
||||||
# Note we may not import webkit stuff yet as fix_harfbuzz didn't run.
|
# Note we may not import webkit stuff yet as fix_harfbuzz didn't run.
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.utils import log
|
||||||
log.init_log(args)
|
log.init_log(args)
|
||||||
log.init.debug("Log initialized.")
|
log.init.debug("Log initialized.")
|
||||||
log.init.debug("Doing early init.")
|
log.init.debug("Doing early init.")
|
||||||
@ -113,10 +113,10 @@ def main():
|
|||||||
earlyinit.check_pkg_resources()
|
earlyinit.check_pkg_resources()
|
||||||
earlyinit.check_pypeg2()
|
earlyinit.check_pypeg2()
|
||||||
# We do this import late as we need to fix harfbuzz first.
|
# We do this import late as we need to fix harfbuzz first.
|
||||||
from qutebrowser.app import Application
|
from qutebrowser import app
|
||||||
from qutebrowser.utils.debug import trace_lines
|
from qutebrowser.utils import debug
|
||||||
import PyQt5.QtWidgets as QtWidgets
|
import PyQt5.QtWidgets as QtWidgets
|
||||||
app = Application(args)
|
app = app.Application(args)
|
||||||
# We set qApp explicitely here to reduce the risk of segfaults while
|
# We set qApp explicitely here to reduce the risk of segfaults while
|
||||||
# quitting.
|
# quitting.
|
||||||
# See https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/561303/comments/7
|
# See https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/561303/comments/7
|
||||||
@ -127,6 +127,6 @@ def main():
|
|||||||
ret = app.exec_()
|
ret = app.exec_()
|
||||||
if args.debug_exit:
|
if args.debug_exit:
|
||||||
print("Now logging late shutdown.", file=sys.stderr)
|
print("Now logging late shutdown.", file=sys.stderr)
|
||||||
trace_lines(True)
|
debug.trace_lines(True)
|
||||||
QtWidgets.qApp = None
|
QtWidgets.qApp = None
|
||||||
return ret
|
return ret
|
||||||
|
@ -19,13 +19,13 @@
|
|||||||
"""Tests for qutebrowser.config.conftypes."""
|
"""Tests for qutebrowser.config.conftypes."""
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
import unittest.mock as mock
|
|
||||||
import re
|
import re
|
||||||
from collections import namedtuple
|
import collections
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
import qutebrowser.config.conftypes as conftypes
|
from qutebrowser.config import conftypes
|
||||||
from qutebrowser.test.stubs import FakeCmdUtils, FakeCommand
|
from qutebrowser.test import stubs
|
||||||
from qutebrowser.utils.debug import qenum_key
|
from qutebrowser.utils import debug
|
||||||
|
|
||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QUrl
|
||||||
from PyQt5.QtGui import QColor, QFont
|
from PyQt5.QtGui import QColor, QFont
|
||||||
@ -37,9 +37,10 @@ class Font(QFont):
|
|||||||
"""A QFont with a nicer repr()."""
|
"""A QFont with a nicer repr()."""
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
weight = debug.qenum_key(QFont, self.weight(), add_base=True,
|
||||||
|
klass=QFont.Weight)
|
||||||
return '<Font family={}, pt={}, px={}, weight={}, style={}>'.format(
|
return '<Font family={}, pt={}, px={}, weight={}, style={}>'.format(
|
||||||
self.family(), self.pointSize(), self.pixelSize(),
|
self.family(), self.pointSize(), self.pixelSize(), weight,
|
||||||
qenum_key(QFont, self.weight(), add_base=True, klass=QFont.Weight),
|
|
||||||
self.style())
|
self.style())
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -853,10 +854,10 @@ class CommandTests(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.old_cmdutils = conftypes.cmdutils
|
self.old_cmdutils = conftypes.cmdutils
|
||||||
commands = {
|
commands = {
|
||||||
'cmd1': FakeCommand("desc 1"),
|
'cmd1': stubs.FakeCommand("desc 1"),
|
||||||
'cmd2': FakeCommand("desc 2"),
|
'cmd2': stubs.FakeCommand("desc 2"),
|
||||||
}
|
}
|
||||||
conftypes.cmdutils = FakeCmdUtils(commands)
|
conftypes.cmdutils = stubs.FakeCmdUtils(commands)
|
||||||
self.t = conftypes.Command()
|
self.t = conftypes.Command()
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@ -1057,7 +1058,8 @@ class QssColorTests(QtColorTests):
|
|||||||
self.assertEqual(self.t.transform(v), v, v)
|
self.assertEqual(self.t.transform(v), v, v)
|
||||||
|
|
||||||
|
|
||||||
FontDesc = namedtuple('FontDesc', ['style', 'weight', 'pt', 'px', 'family'])
|
FontDesc = collections.namedtuple('FontDesc',
|
||||||
|
['style', 'weight', 'pt', 'px', 'family'])
|
||||||
|
|
||||||
|
|
||||||
class FontTests(unittest.TestCase):
|
class FontTests(unittest.TestCase):
|
||||||
|
@ -20,13 +20,13 @@
|
|||||||
"""Helpers needed by tests."""
|
"""Helpers needed by tests."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from contextlib import contextmanager
|
import contextlib
|
||||||
from unittest.mock import create_autospec
|
from unittest import mock
|
||||||
|
|
||||||
from PyQt5.QtGui import QKeyEvent
|
from PyQt5.QtGui import QKeyEvent
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextlib.contextmanager
|
||||||
def environ_set_temp(name, value):
|
def environ_set_temp(name, value):
|
||||||
"""Set a temporary environment variable."""
|
"""Set a temporary environment variable."""
|
||||||
try:
|
try:
|
||||||
@ -43,8 +43,8 @@ def environ_set_temp(name, value):
|
|||||||
|
|
||||||
def fake_keyevent(key, modifiers=0, text=''):
|
def fake_keyevent(key, modifiers=0, text=''):
|
||||||
"""Generate a new fake QKeyPressEvent."""
|
"""Generate a new fake QKeyPressEvent."""
|
||||||
mock = create_autospec(QKeyEvent, instance=True)
|
evtmock = mock.create_autospec(QKeyEvent, instance=True)
|
||||||
mock.key.return_value = key
|
evtmock.key.return_value = key
|
||||||
mock.modifiers.return_value = modifiers
|
evtmock.modifiers.return_value = modifiers
|
||||||
mock.text.return_value = text
|
evtmock.text.return_value = text
|
||||||
return mock
|
return evtmock
|
||||||
|
@ -23,14 +23,14 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import Mock, patch
|
from unittest import mock
|
||||||
|
|
||||||
import qutebrowser.keyinput.basekeyparser as basekeyparser
|
|
||||||
from qutebrowser.test.stubs import ConfigStub
|
|
||||||
from qutebrowser.test.helpers import fake_keyevent
|
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
|
|
||||||
|
from qutebrowser.keyinput import basekeyparser
|
||||||
|
from qutebrowser.test import stubs, helpers
|
||||||
|
|
||||||
|
|
||||||
CONFIG = {'test': {'<Ctrl-a>': 'ctrla',
|
CONFIG = {'test': {'<Ctrl-a>': 'ctrla',
|
||||||
'a': 'a',
|
'a': 'a',
|
||||||
'ba': 'ba',
|
'ba': 'ba',
|
||||||
@ -42,7 +42,7 @@ CONFIG = {'test': {'<Ctrl-a>': 'ctrla',
|
|||||||
|
|
||||||
def setUpModule():
|
def setUpModule():
|
||||||
"""Mock out some imports in basekeyparser."""
|
"""Mock out some imports in basekeyparser."""
|
||||||
basekeyparser.QObject = Mock()
|
basekeyparser.QObject = mock.Mock()
|
||||||
logging.disable(logging.WARNING)
|
logging.disable(logging.WARNING)
|
||||||
|
|
||||||
|
|
||||||
@ -99,8 +99,8 @@ class ReadConfigTests(unittest.TestCase):
|
|||||||
"""Test reading the config."""
|
"""Test reading the config."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
basekeyparser.config = ConfigStub(CONFIG)
|
basekeyparser.config = stubs.ConfigStub(CONFIG)
|
||||||
basekeyparser.Timer = Mock()
|
basekeyparser.usertypes.Timer = mock.Mock()
|
||||||
|
|
||||||
def test_read_config_invalid(self):
|
def test_read_config_invalid(self):
|
||||||
"""Test reading config without setting it before."""
|
"""Test reading config without setting it before."""
|
||||||
@ -131,31 +131,32 @@ class SpecialKeysTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
patcher = patch('qutebrowser.keyinput.basekeyparser.Timer',
|
patcher = mock.patch(
|
||||||
autospec=True)
|
'qutebrowser.keyinput.basekeyparser.usertypes.Timer',
|
||||||
|
autospec=True)
|
||||||
patcher.start()
|
patcher.start()
|
||||||
self.addCleanup(patcher.stop)
|
self.addCleanup(patcher.stop)
|
||||||
basekeyparser.config = ConfigStub(CONFIG)
|
basekeyparser.config = stubs.ConfigStub(CONFIG)
|
||||||
self.kp = basekeyparser.BaseKeyParser()
|
self.kp = basekeyparser.BaseKeyParser()
|
||||||
self.kp.execute = Mock()
|
self.kp.execute = mock.Mock()
|
||||||
self.kp.read_config('test')
|
self.kp.read_config('test')
|
||||||
|
|
||||||
def test_valid_key(self):
|
def test_valid_key(self):
|
||||||
"""Test a valid special keyevent."""
|
"""Test a valid special keyevent."""
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, Qt.ControlModifier))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, Qt.ControlModifier))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_X, Qt.ControlModifier))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, Qt.ControlModifier))
|
||||||
self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special)
|
self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special)
|
||||||
|
|
||||||
def test_invalid_key(self):
|
def test_invalid_key(self):
|
||||||
"""Test an invalid special keyevent."""
|
"""Test an invalid special keyevent."""
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, (Qt.ControlModifier |
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, (Qt.ControlModifier |
|
||||||
Qt.AltModifier)))
|
Qt.AltModifier)))
|
||||||
self.assertFalse(self.kp.execute.called)
|
self.assertFalse(self.kp.execute.called)
|
||||||
|
|
||||||
def test_keychain(self):
|
def test_keychain(self):
|
||||||
"""Test a keychain."""
|
"""Test a keychain."""
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_B))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_B))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A))
|
||||||
self.assertFalse(self.kp.execute.called)
|
self.assertFalse(self.kp.execute.called)
|
||||||
|
|
||||||
|
|
||||||
@ -170,35 +171,35 @@ class KeyChainTests(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up mocks and read the test config."""
|
"""Set up mocks and read the test config."""
|
||||||
basekeyparser.config = ConfigStub(CONFIG)
|
basekeyparser.config = stubs.ConfigStub(CONFIG)
|
||||||
self.timermock = Mock()
|
self.timermock = mock.Mock()
|
||||||
basekeyparser.Timer = Mock(return_value=self.timermock)
|
basekeyparser.usertypes.Timer = mock.Mock(return_value=self.timermock)
|
||||||
self.kp = basekeyparser.BaseKeyParser(supports_chains=True,
|
self.kp = basekeyparser.BaseKeyParser(supports_chains=True,
|
||||||
supports_count=False)
|
supports_count=False)
|
||||||
self.kp.execute = Mock()
|
self.kp.execute = mock.Mock()
|
||||||
self.kp.read_config('test')
|
self.kp.read_config('test')
|
||||||
|
|
||||||
def test_valid_special_key(self):
|
def test_valid_special_key(self):
|
||||||
"""Test valid special key."""
|
"""Test valid special key."""
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, Qt.ControlModifier))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, Qt.ControlModifier))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_X, Qt.ControlModifier))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, Qt.ControlModifier))
|
||||||
self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special)
|
self.kp.execute.assert_called_once_with('ctrla', self.kp.Type.special)
|
||||||
self.assertEqual(self.kp._keystring, '')
|
self.assertEqual(self.kp._keystring, '')
|
||||||
|
|
||||||
def test_invalid_special_key(self):
|
def test_invalid_special_key(self):
|
||||||
"""Test invalid special key."""
|
"""Test invalid special key."""
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, (Qt.ControlModifier |
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, (Qt.ControlModifier |
|
||||||
Qt.AltModifier)))
|
Qt.AltModifier)))
|
||||||
self.assertFalse(self.kp.execute.called)
|
self.assertFalse(self.kp.execute.called)
|
||||||
self.assertEqual(self.kp._keystring, '')
|
self.assertEqual(self.kp._keystring, '')
|
||||||
|
|
||||||
def test_keychain(self):
|
def test_keychain(self):
|
||||||
"""Test valid keychain."""
|
"""Test valid keychain."""
|
||||||
# Press 'x' which is ignored because of no match
|
# Press 'x' which is ignored because of no match
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_X, text='x'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, text='x'))
|
||||||
# Then start the real chain
|
# Then start the real chain
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_B, text='b'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, text='a'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
|
||||||
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None)
|
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None)
|
||||||
self.assertEqual(self.kp._keystring, '')
|
self.assertEqual(self.kp._keystring, '')
|
||||||
|
|
||||||
@ -206,9 +207,10 @@ class KeyChainTests(unittest.TestCase):
|
|||||||
"""Test ambigious keychain."""
|
"""Test ambigious keychain."""
|
||||||
# We start with 'a' where the keychain gives us an ambigious result.
|
# We start with 'a' where the keychain gives us an ambigious result.
|
||||||
# Then we check if the timer has been set up correctly
|
# Then we check if the timer has been set up correctly
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, text='a'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
|
||||||
self.assertFalse(self.kp.execute.called)
|
self.assertFalse(self.kp.execute.called)
|
||||||
basekeyparser.Timer.assert_called_once_with(self.kp, 'ambigious_match')
|
basekeyparser.usertypes.Timer.assert_called_once_with(
|
||||||
|
self.kp, 'ambigious_match')
|
||||||
self.timermock.setSingleShot.assert_called_once_with(True)
|
self.timermock.setSingleShot.assert_called_once_with(True)
|
||||||
self.timermock.setInterval.assert_called_once_with(100)
|
self.timermock.setInterval.assert_called_once_with(100)
|
||||||
self.assertTrue(self.timermock.timeout.connect.called)
|
self.assertTrue(self.timermock.timeout.connect.called)
|
||||||
@ -216,15 +218,15 @@ class KeyChainTests(unittest.TestCase):
|
|||||||
self.timermock.start.assert_called_once_with()
|
self.timermock.start.assert_called_once_with()
|
||||||
# Now we type an 'x' and check 'ax' has been executed and the timer
|
# Now we type an 'x' and check 'ax' has been executed and the timer
|
||||||
# stopped.
|
# stopped.
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_X, text='x'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_X, text='x'))
|
||||||
self.kp.execute.assert_called_once_with('ax', self.kp.Type.chain, None)
|
self.kp.execute.assert_called_once_with('ax', self.kp.Type.chain, None)
|
||||||
self.timermock.stop.assert_called_once_with()
|
self.timermock.stop.assert_called_once_with()
|
||||||
self.assertEqual(self.kp._keystring, '')
|
self.assertEqual(self.kp._keystring, '')
|
||||||
|
|
||||||
def test_invalid_keychain(self):
|
def test_invalid_keychain(self):
|
||||||
"""Test invalid keychain."""
|
"""Test invalid keychain."""
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_B, text='b'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_C, text='c'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_C, text='c'))
|
||||||
self.assertEqual(self.kp._keystring, '')
|
self.assertEqual(self.kp._keystring, '')
|
||||||
|
|
||||||
|
|
||||||
@ -233,53 +235,53 @@ class CountTests(unittest.TestCase):
|
|||||||
"""Test execute() with counts."""
|
"""Test execute() with counts."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
basekeyparser.config = ConfigStub(CONFIG)
|
basekeyparser.config = stubs.ConfigStub(CONFIG)
|
||||||
basekeyparser.Timer = Mock()
|
basekeyparser.usertypes.Timer = mock.Mock()
|
||||||
self.kp = basekeyparser.BaseKeyParser(supports_chains=True,
|
self.kp = basekeyparser.BaseKeyParser(supports_chains=True,
|
||||||
supports_count=True)
|
supports_count=True)
|
||||||
self.kp.execute = Mock()
|
self.kp.execute = mock.Mock()
|
||||||
self.kp.read_config('test')
|
self.kp.read_config('test')
|
||||||
|
|
||||||
def test_no_count(self):
|
def test_no_count(self):
|
||||||
"""Test with no count added."""
|
"""Test with no count added."""
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_B, text='b'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, text='a'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
|
||||||
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None)
|
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, None)
|
||||||
self.assertEqual(self.kp._keystring, '')
|
self.assertEqual(self.kp._keystring, '')
|
||||||
|
|
||||||
def test_count_0(self):
|
def test_count_0(self):
|
||||||
"""Test with count=0."""
|
"""Test with count=0."""
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_0, text='0'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_0, text='0'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_B, text='b'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, text='a'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
|
||||||
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, 0)
|
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, 0)
|
||||||
self.assertEqual(self.kp._keystring, '')
|
self.assertEqual(self.kp._keystring, '')
|
||||||
|
|
||||||
def test_count_42(self):
|
def test_count_42(self):
|
||||||
"""Test with count=42."""
|
"""Test with count=42."""
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_4, text='4'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_4, text='4'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_2, text='2'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_2, text='2'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_B, text='b'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='b'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, text='a'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='a'))
|
||||||
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, 42)
|
self.kp.execute.assert_called_once_with('ba', self.kp.Type.chain, 42)
|
||||||
self.assertEqual(self.kp._keystring, '')
|
self.assertEqual(self.kp._keystring, '')
|
||||||
|
|
||||||
def test_count_42_invalid(self):
|
def test_count_42_invalid(self):
|
||||||
"""Test with count=42 and invalid command."""
|
"""Test with count=42 and invalid command."""
|
||||||
# Invalid call with ccx gets ignored
|
# Invalid call with ccx gets ignored
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_4, text='4'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_4, text='4'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_2, text='2'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_2, text='2'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_B, text='c'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='c'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, text='c'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='c'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, text='x'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='x'))
|
||||||
self.assertFalse(self.kp.execute.called)
|
self.assertFalse(self.kp.execute.called)
|
||||||
self.assertEqual(self.kp._keystring, '')
|
self.assertEqual(self.kp._keystring, '')
|
||||||
# Valid call with ccc gets the correct count
|
# Valid call with ccc gets the correct count
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_4, text='2'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_4, text='2'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_2, text='3'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_2, text='3'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_B, text='c'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_B, text='c'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, text='c'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='c'))
|
||||||
self.kp.handle(fake_keyevent(Qt.Key_A, text='c'))
|
self.kp.handle(helpers.fake_keyevent(Qt.Key_A, text='c'))
|
||||||
self.kp.execute.assert_called_once_with('ccc', self.kp.Type.chain, 23)
|
self.kp.execute.assert_called_once_with('ccc', self.kp.Type.chain, 23)
|
||||||
self.assertEqual(self.kp._keystring, '')
|
self.assertEqual(self.kp._keystring, '')
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
"""Fake objects/stubs."""
|
"""Fake objects/stubs."""
|
||||||
|
|
||||||
from unittest.mock import Mock
|
from unittest import mock
|
||||||
|
|
||||||
from PyQt5.QtCore import QPoint, QProcess
|
from PyQt5.QtCore import QPoint, QProcess
|
||||||
from PyQt5.QtWebKit import QWebElement
|
from PyQt5.QtWebKit import QWebElement
|
||||||
@ -73,9 +73,9 @@ class FakeKeyEvent:
|
|||||||
"""Fake QKeyPressEvent stub."""
|
"""Fake QKeyPressEvent stub."""
|
||||||
|
|
||||||
def __init__(self, key, modifiers=0, text=''):
|
def __init__(self, key, modifiers=0, text=''):
|
||||||
self.key = Mock(return_value=key)
|
self.key = mock.Mock(return_value=key)
|
||||||
self.text = Mock(return_value=text)
|
self.text = mock.Mock(return_value=text)
|
||||||
self.modifiers = Mock(return_value=modifiers)
|
self.modifiers = mock.Mock(return_value=modifiers)
|
||||||
|
|
||||||
|
|
||||||
class FakeWebElement:
|
class FakeWebElement:
|
||||||
@ -99,10 +99,10 @@ class FakeWebElement:
|
|||||||
Raise:
|
Raise:
|
||||||
ValueError if element is not null and geometry/frame are not given.
|
ValueError if element is not null and geometry/frame are not given.
|
||||||
"""
|
"""
|
||||||
self.geometry = Mock(return_value=geometry)
|
self.geometry = mock.Mock(return_value=geometry)
|
||||||
self.webFrame = Mock(return_value=frame)
|
self.webFrame = mock.Mock(return_value=frame)
|
||||||
self.isNull = Mock(return_value=null)
|
self.isNull = mock.Mock(return_value=null)
|
||||||
self.tagName = Mock(return_value=tagname)
|
self.tagName = mock.Mock(return_value=tagname)
|
||||||
self._visibility = visibility
|
self._visibility = visibility
|
||||||
self._display = display
|
self._display = display
|
||||||
self._attributes = attributes
|
self._attributes = attributes
|
||||||
@ -170,9 +170,9 @@ class FakeWebFrame:
|
|||||||
"""
|
"""
|
||||||
if scroll is None:
|
if scroll is None:
|
||||||
scroll = QPoint(0, 0)
|
scroll = QPoint(0, 0)
|
||||||
self.geometry = Mock(return_value=geometry)
|
self.geometry = mock.Mock(return_value=geometry)
|
||||||
self.scrollPosition = Mock(return_value=scroll)
|
self.scrollPosition = mock.Mock(return_value=scroll)
|
||||||
self.parentFrame = Mock(return_value=parent)
|
self.parentFrame = mock.Mock(return_value=parent)
|
||||||
|
|
||||||
|
|
||||||
class FakeChildrenFrame:
|
class FakeChildrenFrame:
|
||||||
@ -182,7 +182,7 @@ class FakeChildrenFrame:
|
|||||||
def __init__(self, children=None):
|
def __init__(self, children=None):
|
||||||
if children is None:
|
if children is None:
|
||||||
children = []
|
children = []
|
||||||
self.childFrames = Mock(return_value=children)
|
self.childFrames = mock.Mock(return_value=children)
|
||||||
|
|
||||||
|
|
||||||
class FakeQApplication:
|
class FakeQApplication:
|
||||||
@ -190,8 +190,8 @@ class FakeQApplication:
|
|||||||
"""Stub to insert as QApplication module."""
|
"""Stub to insert as QApplication module."""
|
||||||
|
|
||||||
def __init__(self, focus):
|
def __init__(self, focus):
|
||||||
self.focusWidget = Mock(return_value=focus)
|
self.focusWidget = mock.Mock(return_value=focus)
|
||||||
self.instance = Mock(return_value=self)
|
self.instance = mock.Mock(return_value=self)
|
||||||
|
|
||||||
|
|
||||||
class FakeUrl:
|
class FakeUrl:
|
||||||
@ -199,7 +199,7 @@ class FakeUrl:
|
|||||||
"""QUrl stub which provides .path()."""
|
"""QUrl stub which provides .path()."""
|
||||||
|
|
||||||
def __init__(self, path=None):
|
def __init__(self, path=None):
|
||||||
self.path = Mock(return_value=path)
|
self.path = mock.Mock(return_value=path)
|
||||||
|
|
||||||
|
|
||||||
class FakeNetworkReply:
|
class FakeNetworkReply:
|
||||||
@ -217,7 +217,7 @@ class FakeNetworkReply:
|
|||||||
self.headers = {}
|
self.headers = {}
|
||||||
else:
|
else:
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
self.url = Mock(return_value=url)
|
self.url = mock.Mock(return_value=url)
|
||||||
|
|
||||||
def hasRawHeader(self, name):
|
def hasRawHeader(self, name):
|
||||||
"""Check if the reply has a certain header.
|
"""Check if the reply has a certain header.
|
||||||
@ -282,9 +282,9 @@ class FakeQProcess:
|
|||||||
UnknownError = QProcess.UnknownError
|
UnknownError = QProcess.UnknownError
|
||||||
|
|
||||||
def __init__(self, parent=None): # pylint: disable=unused-argument
|
def __init__(self, parent=None): # pylint: disable=unused-argument
|
||||||
self.finished = Mock()
|
self.finished = mock.Mock()
|
||||||
self.error = Mock()
|
self.error = mock.Mock()
|
||||||
self.start = Mock()
|
self.start = mock.Mock()
|
||||||
|
|
||||||
|
|
||||||
class FakeSignal:
|
class FakeSignal:
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
import os
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from qutebrowser.test.helpers import environ_set_temp
|
from qutebrowser.test import helpers
|
||||||
|
|
||||||
|
|
||||||
class TestEnvironSetTemp(unittest.TestCase):
|
class TestEnvironSetTemp(unittest.TestCase):
|
||||||
@ -33,13 +33,13 @@ class TestEnvironSetTemp(unittest.TestCase):
|
|||||||
def test_environ_set(self):
|
def test_environ_set(self):
|
||||||
"""Test environ_set_temp with something which was set already."""
|
"""Test environ_set_temp with something which was set already."""
|
||||||
os.environ['QUTEBROWSER_ENVIRON_TEST'] = 'oldval'
|
os.environ['QUTEBROWSER_ENVIRON_TEST'] = 'oldval'
|
||||||
with environ_set_temp('QUTEBROWSER_ENVIRON_TEST', 'newval'):
|
with helpers.environ_set_temp('QUTEBROWSER_ENVIRON_TEST', 'newval'):
|
||||||
self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'newval')
|
self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'newval')
|
||||||
self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'oldval')
|
self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'oldval')
|
||||||
|
|
||||||
def test_environ_unset(self):
|
def test_environ_unset(self):
|
||||||
"""Test environ_set_temp with something which wasn't set yet."""
|
"""Test environ_set_temp with something which wasn't set yet."""
|
||||||
with environ_set_temp('QUTEBROWSER_ENVIRON_TEST', 'newval'):
|
with helpers.environ_set_temp('QUTEBROWSER_ENVIRON_TEST', 'newval'):
|
||||||
self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'newval')
|
self.assertEqual(os.environ['QUTEBROWSER_ENVIRON_TEST'], 'newval')
|
||||||
self.assertNotIn('QUTEBROWSER_ENVIRON_TEST', os.environ)
|
self.assertNotIn('QUTEBROWSER_ENVIRON_TEST', os.environ)
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ import os
|
|||||||
import unittest
|
import unittest
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import qutebrowser.utils.http as httputils
|
from qutebrowser.utils import http
|
||||||
from qutebrowser.test.stubs import FakeNetworkReply
|
from qutebrowser.test import stubs
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_NAME = 'qutebrowser-download'
|
DEFAULT_NAME = 'qutebrowser-download'
|
||||||
@ -39,23 +39,23 @@ class AttachmentTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
def _check_filename(self, header, filename):
|
def _check_filename(self, header, filename):
|
||||||
"""Check if the passed header has the given filename."""
|
"""Check if the passed header has the given filename."""
|
||||||
reply = FakeNetworkReply(headers={'Content-Disposition': header})
|
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
|
||||||
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
|
cd_inline, cd_filename = http.parse_content_disposition(reply)
|
||||||
self.assertIsNotNone(cd_filename)
|
self.assertIsNotNone(cd_filename)
|
||||||
self.assertEqual(cd_filename, filename)
|
self.assertEqual(cd_filename, filename)
|
||||||
self.assertFalse(cd_inline)
|
self.assertFalse(cd_inline)
|
||||||
|
|
||||||
def _check_ignored(self, header):
|
def _check_ignored(self, header):
|
||||||
"""Check if the passed header is ignored."""
|
"""Check if the passed header is ignored."""
|
||||||
reply = FakeNetworkReply(headers={'Content-Disposition': header})
|
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
|
||||||
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
|
cd_inline, cd_filename = http.parse_content_disposition(reply)
|
||||||
self.assertEqual(cd_filename, DEFAULT_NAME)
|
self.assertEqual(cd_filename, DEFAULT_NAME)
|
||||||
self.assertTrue(cd_inline)
|
self.assertTrue(cd_inline)
|
||||||
|
|
||||||
def _check_unnamed(self, header):
|
def _check_unnamed(self, header):
|
||||||
"""Check if the passed header results in an unnamed attachment."""
|
"""Check if the passed header results in an unnamed attachment."""
|
||||||
reply = FakeNetworkReply(headers={'Content-Disposition': header})
|
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
|
||||||
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
|
cd_inline, cd_filename = http.parse_content_disposition(reply)
|
||||||
self.assertEqual(cd_filename, DEFAULT_NAME)
|
self.assertEqual(cd_filename, DEFAULT_NAME)
|
||||||
self.assertFalse(cd_inline)
|
self.assertFalse(cd_inline)
|
||||||
|
|
||||||
@ -69,15 +69,15 @@ class InlineTests(unittest.TestCase):
|
|||||||
|
|
||||||
def _check_filename(self, header, filename):
|
def _check_filename(self, header, filename):
|
||||||
"""Check if the passed header has the given filename."""
|
"""Check if the passed header has the given filename."""
|
||||||
reply = FakeNetworkReply(headers={'Content-Disposition': header})
|
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
|
||||||
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
|
cd_inline, cd_filename = http.parse_content_disposition(reply)
|
||||||
self.assertEqual(cd_filename, filename)
|
self.assertEqual(cd_filename, filename)
|
||||||
self.assertTrue(cd_inline)
|
self.assertTrue(cd_inline)
|
||||||
|
|
||||||
def _check_ignored(self, header):
|
def _check_ignored(self, header):
|
||||||
"""Check if the passed header is ignored."""
|
"""Check if the passed header is ignored."""
|
||||||
reply = FakeNetworkReply(headers={'Content-Disposition': header})
|
reply = stubs.FakeNetworkReply(headers={'Content-Disposition': header})
|
||||||
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
|
cd_inline, cd_filename = http.parse_content_disposition(reply)
|
||||||
self.assertEqual(cd_filename, DEFAULT_NAME)
|
self.assertEqual(cd_filename, DEFAULT_NAME)
|
||||||
self.assertTrue(cd_inline)
|
self.assertTrue(cd_inline)
|
||||||
|
|
||||||
@ -134,8 +134,9 @@ class AttachmentTests(AttachmentTestCase):
|
|||||||
|
|
||||||
UA should offer to download the resource.
|
UA should offer to download the resource.
|
||||||
"""
|
"""
|
||||||
reply = FakeNetworkReply(headers={'Content-Disposition': 'attachment'})
|
reply = stubs.FakeNetworkReply(
|
||||||
cd_inline, cd_filename = httputils.parse_content_disposition(reply)
|
headers={'Content-Disposition': 'attachment'})
|
||||||
|
cd_inline, cd_filename = http.parse_content_disposition(reply)
|
||||||
self.assertFalse(cd_inline)
|
self.assertFalse(cd_inline)
|
||||||
self.assertEqual(cd_filename, DEFAULT_NAME)
|
self.assertEqual(cd_filename, DEFAULT_NAME)
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ test_content_disposition.py file.
|
|||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import qutebrowser.utils.http as httputils
|
from qutebrowser.utils import http
|
||||||
from qutebrowser.test.stubs import FakeNetworkReply
|
from qutebrowser.test import stubs
|
||||||
|
|
||||||
|
|
||||||
class ParseContentTypeTests(unittest.TestCase):
|
class ParseContentTypeTests(unittest.TestCase):
|
||||||
@ -35,30 +35,31 @@ class ParseContentTypeTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_not_existing(self):
|
def test_not_existing(self):
|
||||||
"""Test without any Content-Type header."""
|
"""Test without any Content-Type header."""
|
||||||
reply = FakeNetworkReply()
|
reply = stubs.FakeNetworkReply()
|
||||||
mimetype, rest = httputils.parse_content_type(reply)
|
mimetype, rest = http.parse_content_type(reply)
|
||||||
self.assertIsNone(mimetype)
|
self.assertIsNone(mimetype)
|
||||||
self.assertIsNone(rest)
|
self.assertIsNone(rest)
|
||||||
|
|
||||||
def test_mimetype(self):
|
def test_mimetype(self):
|
||||||
"""Test with simple Content-Type header."""
|
"""Test with simple Content-Type header."""
|
||||||
reply = FakeNetworkReply(headers={'Content-Type': 'image/example'})
|
reply = stubs.FakeNetworkReply(
|
||||||
mimetype, rest = httputils.parse_content_type(reply)
|
headers={'Content-Type': 'image/example'})
|
||||||
|
mimetype, rest = http.parse_content_type(reply)
|
||||||
self.assertEqual(mimetype, 'image/example')
|
self.assertEqual(mimetype, 'image/example')
|
||||||
self.assertIsNone(rest)
|
self.assertIsNone(rest)
|
||||||
|
|
||||||
def test_empty(self):
|
def test_empty(self):
|
||||||
"""Test with empty Content-Type header."""
|
"""Test with empty Content-Type header."""
|
||||||
reply = FakeNetworkReply(headers={'Content-Type': ''})
|
reply = stubs.FakeNetworkReply(headers={'Content-Type': ''})
|
||||||
mimetype, rest = httputils.parse_content_type(reply)
|
mimetype, rest = http.parse_content_type(reply)
|
||||||
self.assertEqual(mimetype, '')
|
self.assertEqual(mimetype, '')
|
||||||
self.assertIsNone(rest)
|
self.assertIsNone(rest)
|
||||||
|
|
||||||
def test_additional(self):
|
def test_additional(self):
|
||||||
"""Test with Content-Type header with additional informations."""
|
"""Test with Content-Type header with additional informations."""
|
||||||
reply = FakeNetworkReply(
|
reply = stubs.FakeNetworkReply(
|
||||||
headers={'Content-Type': 'image/example; encoding=UTF-8'})
|
headers={'Content-Type': 'image/example; encoding=UTF-8'})
|
||||||
mimetype, rest = httputils.parse_content_type(reply)
|
mimetype, rest = http.parse_content_type(reply)
|
||||||
self.assertEqual(mimetype, 'image/example')
|
self.assertEqual(mimetype, 'image/example')
|
||||||
self.assertEqual(rest, ' encoding=UTF-8')
|
self.assertEqual(rest, ' encoding=UTF-8')
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ import unittest
|
|||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtWidgets import QStyle, QFrame
|
from PyQt5.QtWidgets import QStyle, QFrame
|
||||||
|
|
||||||
import qutebrowser.utils.debug as debug
|
from qutebrowser.utils import debug
|
||||||
from qutebrowser.test.stubs import FakeSignal
|
from qutebrowser.test import stubs
|
||||||
|
|
||||||
|
|
||||||
class QEnumKeyTests(unittest.TestCase):
|
class QEnumKeyTests(unittest.TestCase):
|
||||||
@ -123,7 +123,7 @@ class TestDebug(unittest.TestCase):
|
|||||||
"""Test signal debug output functions."""
|
"""Test signal debug output functions."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.signal = FakeSignal()
|
self.signal = stubs.FakeSignal()
|
||||||
|
|
||||||
def test_signal_name(self):
|
def test_signal_name(self):
|
||||||
"""Test signal_name()."""
|
"""Test signal_name()."""
|
||||||
|
@ -23,19 +23,19 @@ import os
|
|||||||
import os.path
|
import os.path
|
||||||
import unittest
|
import unittest
|
||||||
import logging
|
import logging
|
||||||
from unittest.mock import Mock
|
from unittest import mock
|
||||||
|
|
||||||
from PyQt5.QtCore import QProcess
|
from PyQt5.QtCore import QProcess
|
||||||
|
|
||||||
import qutebrowser.utils.editor as editorutils
|
from qutebrowser.utils import editor
|
||||||
from qutebrowser.test.stubs import ConfigStub, FakeQProcess
|
from qutebrowser.test import stubs
|
||||||
|
|
||||||
|
|
||||||
def setUpModule():
|
def setUpModule():
|
||||||
"""Disable logging and mock out some imports."""
|
"""Disable logging and mock out some imports."""
|
||||||
logging.disable(logging.INFO)
|
logging.disable(logging.INFO)
|
||||||
editorutils.message = Mock()
|
editor.message = mock.Mock()
|
||||||
editorutils.QProcess = FakeQProcess
|
editor.QProcess = stubs.FakeQProcess
|
||||||
|
|
||||||
|
|
||||||
def tearDownModule():
|
def tearDownModule():
|
||||||
@ -52,18 +52,18 @@ class ArgTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.editor = editorutils.ExternalEditor()
|
self.editor = editor.ExternalEditor()
|
||||||
|
|
||||||
def test_simple_start_args(self):
|
def test_simple_start_args(self):
|
||||||
"""Test starting editor without arguments."""
|
"""Test starting editor without arguments."""
|
||||||
editorutils.config = ConfigStub(
|
editor.config = stubs.ConfigStub(
|
||||||
{'general': {'editor': ['bin'], 'editor-encoding': 'utf-8'}})
|
{'general': {'editor': ['bin'], 'editor-encoding': 'utf-8'}})
|
||||||
self.editor.edit("")
|
self.editor.edit("")
|
||||||
self.editor.proc.start.assert_called_with("bin", [])
|
self.editor.proc.start.assert_called_with("bin", [])
|
||||||
|
|
||||||
def test_start_args(self):
|
def test_start_args(self):
|
||||||
"""Test starting editor with static arguments."""
|
"""Test starting editor with static arguments."""
|
||||||
editorutils.config = ConfigStub(
|
editor.config = stubs.ConfigStub(
|
||||||
{'general': {'editor': ['bin', 'foo', 'bar'],
|
{'general': {'editor': ['bin', 'foo', 'bar'],
|
||||||
'editor-encoding': 'utf-8'}})
|
'editor-encoding': 'utf-8'}})
|
||||||
self.editor.edit("")
|
self.editor.edit("")
|
||||||
@ -71,7 +71,7 @@ class ArgTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_placeholder(self):
|
def test_placeholder(self):
|
||||||
"""Test starting editor with placeholder argument."""
|
"""Test starting editor with placeholder argument."""
|
||||||
editorutils.config = ConfigStub(
|
editor.config = stubs.ConfigStub(
|
||||||
{'general': {'editor': ['bin', 'foo', '{}', 'bar'],
|
{'general': {'editor': ['bin', 'foo', '{}', 'bar'],
|
||||||
'editor-encoding': 'utf-8'}})
|
'editor-encoding': 'utf-8'}})
|
||||||
self.editor.edit("")
|
self.editor.edit("")
|
||||||
@ -81,7 +81,7 @@ class ArgTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_in_arg_placeholder(self):
|
def test_in_arg_placeholder(self):
|
||||||
"""Test starting editor with placeholder argument inside argument."""
|
"""Test starting editor with placeholder argument inside argument."""
|
||||||
editorutils.config = ConfigStub(
|
editor.config = stubs.ConfigStub(
|
||||||
{'general': {'editor': ['bin', 'foo{}bar'],
|
{'general': {'editor': ['bin', 'foo{}bar'],
|
||||||
'editor-encoding': 'utf-8'}})
|
'editor-encoding': 'utf-8'}})
|
||||||
self.editor.edit("")
|
self.editor.edit("")
|
||||||
@ -100,8 +100,8 @@ class FileHandlingTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.editor = editorutils.ExternalEditor()
|
self.editor = editor.ExternalEditor()
|
||||||
editorutils.config = ConfigStub(
|
editor.config = stubs.ConfigStub(
|
||||||
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
|
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
|
||||||
|
|
||||||
def test_file_handling_closed_ok(self):
|
def test_file_handling_closed_ok(self):
|
||||||
@ -139,9 +139,9 @@ class TextModifyTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.editor = editorutils.ExternalEditor()
|
self.editor = editor.ExternalEditor()
|
||||||
self.editor.editing_finished = Mock()
|
self.editor.editing_finished = mock.Mock()
|
||||||
editorutils.config = ConfigStub(
|
editor.config = stubs.ConfigStub(
|
||||||
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
|
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
|
||||||
|
|
||||||
def _write(self, text):
|
def _write(self, text):
|
||||||
@ -209,21 +209,21 @@ class ErrorMessageTests(unittest.TestCase):
|
|||||||
# pylint: disable=maybe-no-member
|
# pylint: disable=maybe-no-member
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.editor = editorutils.ExternalEditor()
|
self.editor = editor.ExternalEditor()
|
||||||
editorutils.config = ConfigStub(
|
editor.config = stubs.ConfigStub(
|
||||||
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
|
{'general': {'editor': [''], 'editor-encoding': 'utf-8'}})
|
||||||
|
|
||||||
def test_proc_error(self):
|
def test_proc_error(self):
|
||||||
"""Test on_proc_error."""
|
"""Test on_proc_error."""
|
||||||
self.editor.edit("")
|
self.editor.edit("")
|
||||||
self.editor.on_proc_error(QProcess.Crashed)
|
self.editor.on_proc_error(QProcess.Crashed)
|
||||||
self.assertTrue(editorutils.message.error.called)
|
self.assertTrue(editor.message.error.called)
|
||||||
|
|
||||||
def test_proc_return(self):
|
def test_proc_return(self):
|
||||||
"""Test on_proc_finished with a bad exit status."""
|
"""Test on_proc_finished with a bad exit status."""
|
||||||
self.editor.edit("")
|
self.editor.edit("")
|
||||||
self.editor.on_proc_closed(1, QProcess.NormalExit)
|
self.editor.on_proc_closed(1, QProcess.NormalExit)
|
||||||
self.assertTrue(editorutils.message.error.called)
|
self.assertTrue(editor.message.error.called)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -26,7 +26,7 @@ import unittest
|
|||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.utils import log
|
||||||
|
|
||||||
|
|
||||||
class BaseTest(unittest.TestCase):
|
class BaseTest(unittest.TestCase):
|
||||||
|
@ -24,14 +24,14 @@ import sys
|
|||||||
import shutil
|
import shutil
|
||||||
import unittest
|
import unittest
|
||||||
import os.path
|
import os.path
|
||||||
from tempfile import mkdtemp
|
import tempfile
|
||||||
|
|
||||||
from PyQt5.QtCore import QStandardPaths, QCoreApplication, Qt
|
from PyQt5.QtCore import QStandardPaths, QCoreApplication, Qt
|
||||||
from PyQt5.QtGui import QColor
|
from PyQt5.QtGui import QColor
|
||||||
|
|
||||||
import qutebrowser.utils.misc as utils
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.test.helpers import environ_set_temp, fake_keyevent
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.qt import QtValueError
|
from qutebrowser.test import helpers
|
||||||
|
|
||||||
|
|
||||||
class Color(QColor):
|
class Color(QColor):
|
||||||
@ -157,14 +157,14 @@ class GetStandardDirLinuxTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.temp_dir = mkdtemp()
|
self.temp_dir = tempfile.mkdtemp()
|
||||||
self.app = QCoreApplication([])
|
self.app = QCoreApplication([])
|
||||||
self.app.setApplicationName('qutebrowser')
|
self.app.setApplicationName('qutebrowser')
|
||||||
|
|
||||||
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
||||||
def test_data_explicit(self):
|
def test_data_explicit(self):
|
||||||
"""Test data dir with XDG_DATA_HOME explicitely set."""
|
"""Test data dir with XDG_DATA_HOME explicitely set."""
|
||||||
with environ_set_temp('XDG_DATA_HOME', self.temp_dir):
|
with helpers.environ_set_temp('XDG_DATA_HOME', self.temp_dir):
|
||||||
cur_dir = utils.get_standard_dir(QStandardPaths.DataLocation)
|
cur_dir = utils.get_standard_dir(QStandardPaths.DataLocation)
|
||||||
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
|
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
|
||||||
'qutebrowser'))
|
'qutebrowser'))
|
||||||
@ -173,7 +173,7 @@ class GetStandardDirLinuxTests(unittest.TestCase):
|
|||||||
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
||||||
def test_config_explicit(self):
|
def test_config_explicit(self):
|
||||||
"""Test config dir with XDG_CONFIG_HOME explicitely set."""
|
"""Test config dir with XDG_CONFIG_HOME explicitely set."""
|
||||||
with environ_set_temp('XDG_CONFIG_HOME', self.temp_dir):
|
with helpers.environ_set_temp('XDG_CONFIG_HOME', self.temp_dir):
|
||||||
cur_dir = utils.get_standard_dir(QStandardPaths.ConfigLocation)
|
cur_dir = utils.get_standard_dir(QStandardPaths.ConfigLocation)
|
||||||
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
|
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
|
||||||
'qutebrowser'))
|
'qutebrowser'))
|
||||||
@ -182,7 +182,7 @@ class GetStandardDirLinuxTests(unittest.TestCase):
|
|||||||
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
||||||
def test_cache_explicit(self):
|
def test_cache_explicit(self):
|
||||||
"""Test cache dir with XDG_CACHE_HOME explicitely set."""
|
"""Test cache dir with XDG_CACHE_HOME explicitely set."""
|
||||||
with environ_set_temp('XDG_CACHE_HOME', self.temp_dir):
|
with helpers.environ_set_temp('XDG_CACHE_HOME', self.temp_dir):
|
||||||
cur_dir = utils.get_standard_dir(QStandardPaths.CacheLocation)
|
cur_dir = utils.get_standard_dir(QStandardPaths.CacheLocation)
|
||||||
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
|
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
|
||||||
'qutebrowser'))
|
'qutebrowser'))
|
||||||
@ -191,7 +191,7 @@ class GetStandardDirLinuxTests(unittest.TestCase):
|
|||||||
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
||||||
def test_data(self):
|
def test_data(self):
|
||||||
"""Test data dir with XDG_DATA_HOME not set."""
|
"""Test data dir with XDG_DATA_HOME not set."""
|
||||||
with environ_set_temp('HOME', self.temp_dir):
|
with helpers.environ_set_temp('HOME', self.temp_dir):
|
||||||
cur_dir = utils.get_standard_dir(QStandardPaths.DataLocation)
|
cur_dir = utils.get_standard_dir(QStandardPaths.DataLocation)
|
||||||
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.local',
|
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.local',
|
||||||
'share', 'qutebrowser'))
|
'share', 'qutebrowser'))
|
||||||
@ -200,7 +200,7 @@ class GetStandardDirLinuxTests(unittest.TestCase):
|
|||||||
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
||||||
def test_config(self):
|
def test_config(self):
|
||||||
"""Test config dir with XDG_CONFIG_HOME not set."""
|
"""Test config dir with XDG_CONFIG_HOME not set."""
|
||||||
with environ_set_temp('HOME', self.temp_dir):
|
with helpers.environ_set_temp('HOME', self.temp_dir):
|
||||||
cur_dir = utils.get_standard_dir(
|
cur_dir = utils.get_standard_dir(
|
||||||
QStandardPaths.ConfigLocation)
|
QStandardPaths.ConfigLocation)
|
||||||
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.config',
|
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.config',
|
||||||
@ -210,7 +210,7 @@ class GetStandardDirLinuxTests(unittest.TestCase):
|
|||||||
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
|
||||||
def test_cache(self):
|
def test_cache(self):
|
||||||
"""Test cache dir with XDG_CACHE_HOME not set."""
|
"""Test cache dir with XDG_CACHE_HOME not set."""
|
||||||
with environ_set_temp('HOME', self.temp_dir):
|
with helpers.environ_set_temp('HOME', self.temp_dir):
|
||||||
cur_dir = utils.get_standard_dir(QStandardPaths.CacheLocation)
|
cur_dir = utils.get_standard_dir(QStandardPaths.CacheLocation)
|
||||||
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.cache',
|
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.cache',
|
||||||
'qutebrowser'))
|
'qutebrowser'))
|
||||||
@ -286,12 +286,12 @@ class InterpolateColorTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_start(self):
|
def test_invalid_start(self):
|
||||||
"""Test an invalid start color."""
|
"""Test an invalid start color."""
|
||||||
with self.assertRaises(QtValueError):
|
with self.assertRaises(qtutils.QtValueError):
|
||||||
utils.interpolate_color(Color(), self.white, 0)
|
utils.interpolate_color(Color(), self.white, 0)
|
||||||
|
|
||||||
def test_invalid_end(self):
|
def test_invalid_end(self):
|
||||||
"""Test an invalid end color."""
|
"""Test an invalid end color."""
|
||||||
with self.assertRaises(QtValueError):
|
with self.assertRaises(qtutils.QtValueError):
|
||||||
utils.interpolate_color(self.white, Color(), 0)
|
utils.interpolate_color(self.white, Color(), 0)
|
||||||
|
|
||||||
def test_invalid_percentage(self):
|
def test_invalid_percentage(self):
|
||||||
@ -464,29 +464,31 @@ class KeyEventToStringTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_only_control(self):
|
def test_only_control(self):
|
||||||
"""Test keyeevent when only control is pressed."""
|
"""Test keyeevent when only control is pressed."""
|
||||||
evt = fake_keyevent(key=Qt.Key_Control, modifiers=Qt.ControlModifier)
|
evt = helpers.fake_keyevent(key=Qt.Key_Control,
|
||||||
|
modifiers=Qt.ControlModifier)
|
||||||
self.assertIsNone(utils.keyevent_to_string(evt))
|
self.assertIsNone(utils.keyevent_to_string(evt))
|
||||||
|
|
||||||
def test_only_hyper_l(self):
|
def test_only_hyper_l(self):
|
||||||
"""Test keyeevent when only Hyper_L is pressed."""
|
"""Test keyeevent when only Hyper_L is pressed."""
|
||||||
evt = fake_keyevent(key=Qt.Key_Hyper_L, modifiers=Qt.MetaModifier)
|
evt = helpers.fake_keyevent(key=Qt.Key_Hyper_L,
|
||||||
|
modifiers=Qt.MetaModifier)
|
||||||
self.assertIsNone(utils.keyevent_to_string(evt))
|
self.assertIsNone(utils.keyevent_to_string(evt))
|
||||||
|
|
||||||
def test_only_key(self):
|
def test_only_key(self):
|
||||||
"""Test with a simple key pressed."""
|
"""Test with a simple key pressed."""
|
||||||
evt = fake_keyevent(key=Qt.Key_A)
|
evt = helpers.fake_keyevent(key=Qt.Key_A)
|
||||||
self.assertEqual(utils.keyevent_to_string(evt), 'A')
|
self.assertEqual(utils.keyevent_to_string(evt), 'A')
|
||||||
|
|
||||||
def test_key_and_modifier(self):
|
def test_key_and_modifier(self):
|
||||||
"""Test with key and modifier pressed."""
|
"""Test with key and modifier pressed."""
|
||||||
evt = fake_keyevent(key=Qt.Key_A, modifiers=Qt.ControlModifier)
|
evt = helpers.fake_keyevent(key=Qt.Key_A, modifiers=Qt.ControlModifier)
|
||||||
self.assertEqual(utils.keyevent_to_string(evt), 'Ctrl+A')
|
self.assertEqual(utils.keyevent_to_string(evt), 'Ctrl+A')
|
||||||
|
|
||||||
def test_key_and_modifiers(self):
|
def test_key_and_modifiers(self):
|
||||||
"""Test with key and multiple modifier pressed."""
|
"""Test with key and multiple modifier pressed."""
|
||||||
evt = fake_keyevent(key=Qt.Key_A,
|
evt = helpers.fake_keyevent(
|
||||||
modifiers=(Qt.ControlModifier | Qt.AltModifier |
|
key=Qt.Key_A, modifiers=(Qt.ControlModifier | Qt.AltModifier |
|
||||||
Qt.MetaModifier | Qt.ShiftModifier))
|
Qt.MetaModifier | Qt.ShiftModifier))
|
||||||
self.assertEqual(utils.keyevent_to_string(evt),
|
self.assertEqual(utils.keyevent_to_string(evt),
|
||||||
'Ctrl+Alt+Meta+Shift+A')
|
'Ctrl+Alt+Meta+Shift+A')
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import sys
|
|||||||
import argparse
|
import argparse
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import qutebrowser.utils.qt as qt
|
from qutebrowser.utils import qt
|
||||||
|
|
||||||
|
|
||||||
class CheckOverflowTests(unittest.TestCase):
|
class CheckOverflowTests(unittest.TestCase):
|
||||||
|
@ -21,12 +21,12 @@
|
|||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import Mock
|
from unittest import mock
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QLineEdit
|
from PyQt5.QtWidgets import QLineEdit
|
||||||
|
|
||||||
import qutebrowser.utils.readline as readline
|
from qutebrowser.utils import readline
|
||||||
from qutebrowser.test.stubs import FakeQApplication
|
from qutebrowser.test import stubs
|
||||||
|
|
||||||
|
|
||||||
class NoneWidgetTests(unittest.TestCase):
|
class NoneWidgetTests(unittest.TestCase):
|
||||||
@ -34,7 +34,7 @@ class NoneWidgetTests(unittest.TestCase):
|
|||||||
"""Tests when the focused widget is None."""
|
"""Tests when the focused widget is None."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
readline.QApplication = FakeQApplication(None)
|
readline.QApplication = stubs.FakeQApplication(None)
|
||||||
self.bridge = readline.ReadlineBridge()
|
self.bridge = readline.ReadlineBridge()
|
||||||
|
|
||||||
def test_none(self):
|
def test_none(self):
|
||||||
@ -50,9 +50,9 @@ class ReadlineBridgeTest(unittest.TestCase):
|
|||||||
"""Tests for readline bridge."""
|
"""Tests for readline bridge."""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.qle = Mock()
|
self.qle = mock.Mock()
|
||||||
self.qle.__class__ = QLineEdit
|
self.qle.__class__ = QLineEdit
|
||||||
readline.QApplication = FakeQApplication(self.qle)
|
readline.QApplication = stubs.FakeQApplication(self.qle)
|
||||||
self.bridge = readline.ReadlineBridge()
|
self.bridge = readline.ReadlineBridge()
|
||||||
|
|
||||||
def _set_selected_text(self, text):
|
def _set_selected_text(self, text):
|
||||||
|
@ -25,8 +25,8 @@ import unittest
|
|||||||
|
|
||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QUrl
|
||||||
|
|
||||||
import qutebrowser.utils.url as urlutils
|
from qutebrowser.utils import url as urlutils
|
||||||
from qutebrowser.test.stubs import ConfigStub
|
from qutebrowser.test import stubs
|
||||||
|
|
||||||
|
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
@ -83,7 +83,7 @@ class SearchUrlTests(unittest.TestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.config = urlutils.config
|
self.config = urlutils.config
|
||||||
urlutils.config = ConfigStub(CONFIG)
|
urlutils.config = stubs.ConfigStub(CONFIG)
|
||||||
|
|
||||||
def test_default_engine(self):
|
def test_default_engine(self):
|
||||||
"""Test default search engine."""
|
"""Test default search engine."""
|
||||||
|
@ -23,9 +23,8 @@ import unittest
|
|||||||
|
|
||||||
from PyQt5.QtCore import QRect, QPoint
|
from PyQt5.QtCore import QRect, QPoint
|
||||||
|
|
||||||
import qutebrowser.utils.webelem as webelem
|
from qutebrowser.utils import webelem
|
||||||
from qutebrowser.test.stubs import (FakeWebElement, FakeWebFrame,
|
from qutebrowser.test import stubs
|
||||||
FakeChildrenFrame, ConfigStub)
|
|
||||||
|
|
||||||
|
|
||||||
class IsVisibleInvalidTests(unittest.TestCase):
|
class IsVisibleInvalidTests(unittest.TestCase):
|
||||||
@ -37,7 +36,7 @@ class IsVisibleInvalidTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.frame = FakeWebFrame(QRect(0, 0, 100, 100))
|
self.frame = stubs.FakeWebFrame(QRect(0, 0, 100, 100))
|
||||||
|
|
||||||
def test_nullelem(self):
|
def test_nullelem(self):
|
||||||
"""Passing an element with isNull() == True.
|
"""Passing an element with isNull() == True.
|
||||||
@ -45,7 +44,7 @@ class IsVisibleInvalidTests(unittest.TestCase):
|
|||||||
geometry() and webFrame() should not be called, and ValueError should
|
geometry() and webFrame() should not be called, and ValueError should
|
||||||
be raised.
|
be raised.
|
||||||
"""
|
"""
|
||||||
elem = FakeWebElement(null=True)
|
elem = stubs.FakeWebElement(null=True)
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
webelem.is_visible(elem, self.frame)
|
webelem.is_visible(elem, self.frame)
|
||||||
elem.isNull.assert_called_once_with()
|
elem.isNull.assert_called_once_with()
|
||||||
@ -54,7 +53,7 @@ class IsVisibleInvalidTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_invalid_invisible(self):
|
def test_invalid_invisible(self):
|
||||||
"""Test elements with an invalid geometry which are invisible."""
|
"""Test elements with an invalid geometry which are invisible."""
|
||||||
elem = FakeWebElement(QRect(0, 0, 0, 0), self.frame)
|
elem = stubs.FakeWebElement(QRect(0, 0, 0, 0), self.frame)
|
||||||
self.assertFalse(elem.geometry().isValid())
|
self.assertFalse(elem.geometry().isValid())
|
||||||
self.assertEqual(elem.geometry().x(), 0)
|
self.assertEqual(elem.geometry().x(), 0)
|
||||||
self.assertFalse(webelem.is_visible(elem, self.frame))
|
self.assertFalse(webelem.is_visible(elem, self.frame))
|
||||||
@ -65,7 +64,7 @@ class IsVisibleInvalidTests(unittest.TestCase):
|
|||||||
This seems to happen sometimes in the real world, with real elements
|
This seems to happen sometimes in the real world, with real elements
|
||||||
which *are* visible, but don't have a valid geometry.
|
which *are* visible, but don't have a valid geometry.
|
||||||
"""
|
"""
|
||||||
elem = FakeWebElement(QRect(10, 10, 0, 0), self.frame)
|
elem = stubs.FakeWebElement(QRect(10, 10, 0, 0), self.frame)
|
||||||
self.assertFalse(elem.geometry().isValid())
|
self.assertFalse(elem.geometry().isValid())
|
||||||
self.assertTrue(webelem.is_visible(elem, self.frame))
|
self.assertTrue(webelem.is_visible(elem, self.frame))
|
||||||
|
|
||||||
@ -79,16 +78,17 @@ class IsVisibleScrollTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.frame = FakeWebFrame(QRect(0, 0, 100, 100), scroll=QPoint(10, 10))
|
self.frame = stubs.FakeWebFrame(QRect(0, 0, 100, 100),
|
||||||
|
scroll=QPoint(10, 10))
|
||||||
|
|
||||||
def test_invisible(self):
|
def test_invisible(self):
|
||||||
"""Test elements which should be invisible due to scrolling."""
|
"""Test elements which should be invisible due to scrolling."""
|
||||||
elem = FakeWebElement(QRect(5, 5, 4, 4), self.frame)
|
elem = stubs.FakeWebElement(QRect(5, 5, 4, 4), self.frame)
|
||||||
self.assertFalse(webelem.is_visible(elem, self.frame))
|
self.assertFalse(webelem.is_visible(elem, self.frame))
|
||||||
|
|
||||||
def test_visible(self):
|
def test_visible(self):
|
||||||
"""Test elements which still should be visible after scrolling."""
|
"""Test elements which still should be visible after scrolling."""
|
||||||
elem = FakeWebElement(QRect(10, 10, 1, 1), self.frame)
|
elem = stubs.FakeWebElement(QRect(10, 10, 1, 1), self.frame)
|
||||||
self.assertTrue(webelem.is_visible(elem, self.frame))
|
self.assertTrue(webelem.is_visible(elem, self.frame))
|
||||||
|
|
||||||
|
|
||||||
@ -101,29 +101,30 @@ class IsVisibleCssTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.frame = FakeWebFrame(QRect(0, 0, 100, 100))
|
self.frame = stubs.FakeWebFrame(QRect(0, 0, 100, 100))
|
||||||
|
|
||||||
def test_visibility_visible(self):
|
def test_visibility_visible(self):
|
||||||
"""Check that elements with "visibility = visible" are visible."""
|
"""Check that elements with "visibility = visible" are visible."""
|
||||||
elem = FakeWebElement(QRect(0, 0, 10, 10), self.frame,
|
elem = stubs.FakeWebElement(QRect(0, 0, 10, 10), self.frame,
|
||||||
visibility='visible')
|
visibility='visible')
|
||||||
self.assertTrue(webelem.is_visible(elem, self.frame))
|
self.assertTrue(webelem.is_visible(elem, self.frame))
|
||||||
|
|
||||||
def test_visibility_hidden(self):
|
def test_visibility_hidden(self):
|
||||||
"""Check that elements with "visibility = hidden" are not visible."""
|
"""Check that elements with "visibility = hidden" are not visible."""
|
||||||
elem = FakeWebElement(QRect(0, 0, 10, 10), self.frame,
|
elem = stubs.FakeWebElement(QRect(0, 0, 10, 10), self.frame,
|
||||||
visibility='hidden')
|
visibility='hidden')
|
||||||
self.assertFalse(webelem.is_visible(elem, self.frame))
|
self.assertFalse(webelem.is_visible(elem, self.frame))
|
||||||
|
|
||||||
def test_display_inline(self):
|
def test_display_inline(self):
|
||||||
"""Check that elements with "display = inline" are visible."""
|
"""Check that elements with "display = inline" are visible."""
|
||||||
elem = FakeWebElement(QRect(0, 0, 10, 10), self.frame,
|
elem = stubs.FakeWebElement(QRect(0, 0, 10, 10), self.frame,
|
||||||
display='inline')
|
display='inline')
|
||||||
self.assertTrue(webelem.is_visible(elem, self.frame))
|
self.assertTrue(webelem.is_visible(elem, self.frame))
|
||||||
|
|
||||||
def test_display_none(self):
|
def test_display_none(self):
|
||||||
"""Check that elements with "display = none" are not visible."""
|
"""Check that elements with "display = none" are not visible."""
|
||||||
elem = FakeWebElement(QRect(0, 0, 10, 10), self.frame, display='none')
|
elem = stubs.FakeWebElement(QRect(0, 0, 10, 10), self.frame,
|
||||||
|
display='none')
|
||||||
self.assertFalse(webelem.is_visible(elem, self.frame))
|
self.assertFalse(webelem.is_visible(elem, self.frame))
|
||||||
|
|
||||||
|
|
||||||
@ -158,12 +159,13 @@ class IsVisibleIframeTests(unittest.TestCase):
|
|||||||
##############################
|
##############################
|
||||||
300, 0 300, 300
|
300, 0 300, 300
|
||||||
"""
|
"""
|
||||||
self.frame = FakeWebFrame(QRect(0, 0, 300, 300))
|
self.frame = stubs.FakeWebFrame(QRect(0, 0, 300, 300))
|
||||||
self.iframe = FakeWebFrame(QRect(0, 10, 100, 100), parent=self.frame)
|
self.iframe = stubs.FakeWebFrame(QRect(0, 10, 100, 100),
|
||||||
self.elem1 = FakeWebElement(QRect(0, 0, 10, 10), self.iframe)
|
parent=self.frame)
|
||||||
self.elem2 = FakeWebElement(QRect(20, 90, 10, 10), self.iframe)
|
self.elem1 = stubs.FakeWebElement(QRect(0, 0, 10, 10), self.iframe)
|
||||||
self.elem3 = FakeWebElement(QRect(20, 150, 10, 10), self.iframe)
|
self.elem2 = stubs.FakeWebElement(QRect(20, 90, 10, 10), self.iframe)
|
||||||
self.elem4 = FakeWebElement(QRect(30, 180, 10, 10), self.frame)
|
self.elem3 = stubs.FakeWebElement(QRect(20, 150, 10, 10), self.iframe)
|
||||||
|
self.elem4 = stubs.FakeWebElement(QRect(30, 180, 10, 10), self.frame)
|
||||||
|
|
||||||
def test_not_scrolled(self):
|
def test_not_scrolled(self):
|
||||||
"""Test base situation."""
|
"""Test base situation."""
|
||||||
@ -210,17 +212,17 @@ class IsWritableTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_writable(self):
|
def test_writable(self):
|
||||||
"""Test a normal element."""
|
"""Test a normal element."""
|
||||||
elem = FakeWebElement()
|
elem = stubs.FakeWebElement()
|
||||||
self.assertTrue(webelem.is_writable(elem))
|
self.assertTrue(webelem.is_writable(elem))
|
||||||
|
|
||||||
def test_disabled(self):
|
def test_disabled(self):
|
||||||
"""Test a disabled element."""
|
"""Test a disabled element."""
|
||||||
elem = FakeWebElement(attributes=['disabled'])
|
elem = stubs.FakeWebElement(attributes=['disabled'])
|
||||||
self.assertFalse(webelem.is_writable(elem))
|
self.assertFalse(webelem.is_writable(elem))
|
||||||
|
|
||||||
def test_readonly(self):
|
def test_readonly(self):
|
||||||
"""Test a readonly element."""
|
"""Test a readonly element."""
|
||||||
elem = FakeWebElement(attributes=['readonly'])
|
elem = stubs.FakeWebElement(attributes=['readonly'])
|
||||||
self.assertFalse(webelem.is_writable(elem))
|
self.assertFalse(webelem.is_writable(elem))
|
||||||
|
|
||||||
|
|
||||||
@ -252,7 +254,7 @@ class GetChildFramesTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_single_frame(self):
|
def test_single_frame(self):
|
||||||
"""Test get_child_frames with a single frame without children."""
|
"""Test get_child_frames with a single frame without children."""
|
||||||
frame = FakeChildrenFrame()
|
frame = stubs.FakeChildrenFrame()
|
||||||
children = webelem.get_child_frames(frame)
|
children = webelem.get_child_frames(frame)
|
||||||
self.assertEqual(len(children), 1)
|
self.assertEqual(len(children), 1)
|
||||||
self.assertIs(children[0], frame)
|
self.assertIs(children[0], frame)
|
||||||
@ -265,9 +267,9 @@ class GetChildFramesTests(unittest.TestCase):
|
|||||||
/ \
|
/ \
|
||||||
child1 o o child2
|
child1 o o child2
|
||||||
"""
|
"""
|
||||||
child1 = FakeChildrenFrame()
|
child1 = stubs.FakeChildrenFrame()
|
||||||
child2 = FakeChildrenFrame()
|
child2 = stubs.FakeChildrenFrame()
|
||||||
parent = FakeChildrenFrame([child1, child2])
|
parent = stubs.FakeChildrenFrame([child1, child2])
|
||||||
children = webelem.get_child_frames(parent)
|
children = webelem.get_child_frames(parent)
|
||||||
self.assertEqual(len(children), 3)
|
self.assertEqual(len(children), 3)
|
||||||
self.assertIs(children[0], parent)
|
self.assertIs(children[0], parent)
|
||||||
@ -286,10 +288,10 @@ class GetChildFramesTests(unittest.TestCase):
|
|||||||
/\ /\
|
/\ /\
|
||||||
o o o o second
|
o o o o second
|
||||||
"""
|
"""
|
||||||
second = [FakeChildrenFrame() for _ in range(4)]
|
second = [stubs.FakeChildrenFrame() for _ in range(4)]
|
||||||
first = [FakeChildrenFrame(second[0:2]),
|
first = [stubs.FakeChildrenFrame(second[0:2]),
|
||||||
FakeChildrenFrame(second[2:4])]
|
stubs.FakeChildrenFrame(second[2:4])]
|
||||||
root = FakeChildrenFrame(first)
|
root = stubs.FakeChildrenFrame(first)
|
||||||
children = webelem.get_child_frames(root)
|
children = webelem.get_child_frames(root)
|
||||||
self.assertEqual(len(children), 7)
|
self.assertEqual(len(children), 7)
|
||||||
self.assertIs(children[0], root)
|
self.assertIs(children[0], root)
|
||||||
@ -307,175 +309,189 @@ class IsEditableTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_input_plain(self):
|
def test_input_plain(self):
|
||||||
"""Test with plain input element."""
|
"""Test with plain input element."""
|
||||||
elem = FakeWebElement(tagname='input')
|
elem = stubs.FakeWebElement(tagname='input')
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_text(self):
|
def test_input_text(self):
|
||||||
"""Test with text input element."""
|
"""Test with text input element."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'type': 'text'})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'type': 'text'})
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_text_caps(self):
|
def test_input_text_caps(self):
|
||||||
"""Test with text input element with caps attributes."""
|
"""Test with text input element with caps attributes."""
|
||||||
elem = FakeWebElement(tagname='INPUT', attributes={'TYPE': 'TEXT'})
|
elem = stubs.FakeWebElement(tagname='INPUT',
|
||||||
|
attributes={'TYPE': 'TEXT'})
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_email(self):
|
def test_input_email(self):
|
||||||
"""Test with email input element."""
|
"""Test with email input element."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'type': 'email'})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'type': 'email'})
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_url(self):
|
def test_input_url(self):
|
||||||
"""Test with url input element."""
|
"""Test with url input element."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'type': 'url'})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'type': 'url'})
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_tel(self):
|
def test_input_tel(self):
|
||||||
"""Test with tel input element."""
|
"""Test with tel input element."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'type': 'tel'})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'type': 'tel'})
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_number(self):
|
def test_input_number(self):
|
||||||
"""Test with number input element."""
|
"""Test with number input element."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'type': 'number'})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'type': 'number'})
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_password(self):
|
def test_input_password(self):
|
||||||
"""Test with password input element."""
|
"""Test with password input element."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'type': 'password'})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'type': 'password'})
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_search(self):
|
def test_input_search(self):
|
||||||
"""Test with search input element."""
|
"""Test with search input element."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'type': 'search'})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'type': 'search'})
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_button(self):
|
def test_input_button(self):
|
||||||
"""Button should not be editable."""
|
"""Button should not be editable."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'type': 'button'})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'type': 'button'})
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_checkbox(self):
|
def test_input_checkbox(self):
|
||||||
"""Checkbox should not be editable."""
|
"""Checkbox should not be editable."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'type': 'checkbox'})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'type': 'checkbox'})
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_textarea(self):
|
def test_textarea(self):
|
||||||
"""Test textarea element."""
|
"""Test textarea element."""
|
||||||
elem = FakeWebElement(tagname='textarea')
|
elem = stubs.FakeWebElement(tagname='textarea')
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_select(self):
|
def test_select(self):
|
||||||
"""Test selectbox."""
|
"""Test selectbox."""
|
||||||
elem = FakeWebElement(tagname='select')
|
elem = stubs.FakeWebElement(tagname='select')
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_disabled(self):
|
def test_input_disabled(self):
|
||||||
"""Test disabled input element."""
|
"""Test disabled input element."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'disabled': None})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'disabled': None})
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_input_readonly(self):
|
def test_input_readonly(self):
|
||||||
"""Test readonly input element."""
|
"""Test readonly input element."""
|
||||||
elem = FakeWebElement(tagname='input', attributes={'readonly': None})
|
elem = stubs.FakeWebElement(tagname='input',
|
||||||
|
attributes={'readonly': None})
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_textarea_disabled(self):
|
def test_textarea_disabled(self):
|
||||||
"""Test disabled textarea element."""
|
"""Test disabled textarea element."""
|
||||||
elem = FakeWebElement(tagname='textarea',
|
elem = stubs.FakeWebElement(tagname='textarea',
|
||||||
attributes={'disabled': None})
|
attributes={'disabled': None})
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_textarea_readonly(self):
|
def test_textarea_readonly(self):
|
||||||
"""Test readonly textarea element."""
|
"""Test readonly textarea element."""
|
||||||
elem = FakeWebElement(tagname='textarea',
|
elem = stubs.FakeWebElement(tagname='textarea',
|
||||||
attributes={'readonly': None})
|
attributes={'readonly': None})
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_embed_true(self):
|
def test_embed_true(self):
|
||||||
"""Test embed-element with insert-mode-on-plugins true."""
|
"""Test embed-element with insert-mode-on-plugins true."""
|
||||||
webelem.config = ConfigStub({'input':
|
webelem.config = stubs.ConfigStub({'input':
|
||||||
{'insert-mode-on-plugins': True}})
|
{'insert-mode-on-plugins': True}})
|
||||||
elem = FakeWebElement(tagname='embed')
|
elem = stubs.FakeWebElement(tagname='embed')
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_applet_true(self):
|
def test_applet_true(self):
|
||||||
"""Test applet-element with insert-mode-on-plugins true."""
|
"""Test applet-element with insert-mode-on-plugins true."""
|
||||||
webelem.config = ConfigStub({'input':
|
webelem.config = stubs.ConfigStub({'input':
|
||||||
{'insert-mode-on-plugins': True}})
|
{'insert-mode-on-plugins': True}})
|
||||||
elem = FakeWebElement(tagname='applet')
|
elem = stubs.FakeWebElement(tagname='applet')
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_embed_false(self):
|
def test_embed_false(self):
|
||||||
"""Test embed-element with insert-mode-on-plugins false."""
|
"""Test embed-element with insert-mode-on-plugins false."""
|
||||||
webelem.config = ConfigStub({'input':
|
webelem.config = stubs.ConfigStub({'input':
|
||||||
{'insert-mode-on-plugins': False}})
|
{'insert-mode-on-plugins': False}})
|
||||||
elem = FakeWebElement(tagname='embed')
|
elem = stubs.FakeWebElement(tagname='embed')
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_applet_false(self):
|
def test_applet_false(self):
|
||||||
"""Test applet-element with insert-mode-on-plugins false."""
|
"""Test applet-element with insert-mode-on-plugins false."""
|
||||||
webelem.config = ConfigStub({'input':
|
webelem.config = stubs.ConfigStub({'input':
|
||||||
{'insert-mode-on-plugins': False}})
|
{'insert-mode-on-plugins': False}})
|
||||||
elem = FakeWebElement(tagname='applet')
|
elem = stubs.FakeWebElement(tagname='applet')
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_object_no_type(self):
|
def test_object_no_type(self):
|
||||||
"""Test object-element without type."""
|
"""Test object-element without type."""
|
||||||
elem = FakeWebElement(tagname='object')
|
elem = stubs.FakeWebElement(tagname='object')
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_object_image(self):
|
def test_object_image(self):
|
||||||
"""Test object-element with image type."""
|
"""Test object-element with image type."""
|
||||||
elem = FakeWebElement(tagname='object',
|
elem = stubs.FakeWebElement(tagname='object',
|
||||||
attributes={'type': 'image/gif'})
|
attributes={'type': 'image/gif'})
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_object_application(self):
|
def test_object_application(self):
|
||||||
"""Test object-element with application type."""
|
"""Test object-element with application type."""
|
||||||
webelem.config = ConfigStub({'input':
|
webelem.config = stubs.ConfigStub({'input':
|
||||||
{'insert-mode-on-plugins': True}})
|
{'insert-mode-on-plugins': True}})
|
||||||
elem = FakeWebElement(tagname='object',
|
elem = stubs.FakeWebElement(tagname='object',
|
||||||
attributes={'type': 'application/foo'})
|
attributes={'type': 'application/foo'})
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_object_application_false(self):
|
def test_object_application_false(self):
|
||||||
"""Test object-element with application type but not ...-on-plugins."""
|
"""Test object-element with application type but not ...-on-plugins."""
|
||||||
webelem.config = ConfigStub({'input':
|
webelem.config = stubs.ConfigStub({'input':
|
||||||
{'insert-mode-on-plugins': False}})
|
{'insert-mode-on-plugins': False}})
|
||||||
elem = FakeWebElement(tagname='object',
|
elem = stubs.FakeWebElement(tagname='object',
|
||||||
attributes={'type': 'application/foo'})
|
attributes={'type': 'application/foo'})
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_object_classid(self):
|
def test_object_classid(self):
|
||||||
"""Test object-element with classid."""
|
"""Test object-element with classid."""
|
||||||
webelem.config = ConfigStub({'input':
|
webelem.config = stubs.ConfigStub({'input':
|
||||||
{'insert-mode-on-plugins': True}})
|
{'insert-mode-on-plugins': True}})
|
||||||
elem = FakeWebElement(tagname='object',
|
elem = stubs.FakeWebElement(tagname='object',
|
||||||
attributes={'type': 'foo', 'classid': 'foo'})
|
attributes={'type': 'foo',
|
||||||
|
'classid': 'foo'})
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_object_classid_false(self):
|
def test_object_classid_false(self):
|
||||||
"""Test object-element with classid but not insert-mode-on-plugins."""
|
"""Test object-element with classid but not insert-mode-on-plugins."""
|
||||||
webelem.config = ConfigStub({'input':
|
webelem.config = stubs.ConfigStub({'input':
|
||||||
{'insert-mode-on-plugins': False}})
|
{'insert-mode-on-plugins': False}})
|
||||||
elem = FakeWebElement(tagname='object',
|
elem = stubs.FakeWebElement(tagname='object',
|
||||||
attributes={'type': 'foo', 'classid': 'foo'})
|
attributes={'type': 'foo',
|
||||||
|
'classid': 'foo'})
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_div_empty(self):
|
def test_div_empty(self):
|
||||||
"""Test div-element without class."""
|
"""Test div-element without class."""
|
||||||
elem = FakeWebElement(tagname='div')
|
elem = stubs.FakeWebElement(tagname='div')
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_div_noneditable(self):
|
def test_div_noneditable(self):
|
||||||
"""Test div-element with non-editableclass."""
|
"""Test div-element with non-editableclass."""
|
||||||
elem = FakeWebElement(tagname='div', classes='foo-kix-bar')
|
elem = stubs.FakeWebElement(tagname='div', classes='foo-kix-bar')
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_div_xik(self):
|
def test_div_xik(self):
|
||||||
"""Test div-element with xik class."""
|
"""Test div-element with xik class."""
|
||||||
elem = FakeWebElement(tagname='div', classes='foo kix-foo')
|
elem = stubs.FakeWebElement(tagname='div', classes='foo kix-foo')
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_div_xik_caps(self):
|
def test_div_xik_caps(self):
|
||||||
@ -483,12 +499,13 @@ class IsEditableTests(unittest.TestCase):
|
|||||||
|
|
||||||
This tests if classes are case sensitive as they should.
|
This tests if classes are case sensitive as they should.
|
||||||
"""
|
"""
|
||||||
elem = FakeWebElement(tagname='div', classes='KIX-FOO')
|
elem = stubs.FakeWebElement(tagname='div', classes='KIX-FOO')
|
||||||
self.assertFalse(webelem.is_editable(elem))
|
self.assertFalse(webelem.is_editable(elem))
|
||||||
|
|
||||||
def test_div_codemirror(self):
|
def test_div_codemirror(self):
|
||||||
"""Test div-element with codemirror class."""
|
"""Test div-element with codemirror class."""
|
||||||
elem = FakeWebElement(tagname='div', classes='foo CodeMirror-foo')
|
elem = stubs.FakeWebElement(tagname='div',
|
||||||
|
classes='foo CodeMirror-foo')
|
||||||
self.assertTrue(webelem.is_editable(elem))
|
self.assertTrue(webelem.is_editable(elem))
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from qutebrowser.utils.usertypes import enum
|
from qutebrowser.utils import usertypes
|
||||||
|
|
||||||
# FIXME: Add some more tests, e.g. for is_int
|
# FIXME: Add some more tests, e.g. for is_int
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ class EnumTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.enum = enum('Enum', 'one', 'two')
|
self.enum = usertypes.enum('Enum', 'one', 'two')
|
||||||
|
|
||||||
def test_values(self):
|
def test_values(self):
|
||||||
"""Test if enum members resolve to the right values."""
|
"""Test if enum members resolve to the right values."""
|
||||||
@ -54,7 +54,7 @@ class EnumTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_start(self):
|
def test_start(self):
|
||||||
"""Test the start= argument."""
|
"""Test the start= argument."""
|
||||||
e = enum('Enum', 'three', 'four', start=3)
|
e = usertypes.enum('Enum', 'three', 'four', start=3)
|
||||||
self.assertEqual(e.three.value, 3)
|
self.assertEqual(e.three.value, 3)
|
||||||
self.assertEqual(e.four.value, 4)
|
self.assertEqual(e.four.value, 4)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from qutebrowser.utils.usertypes import NeighborList
|
from qutebrowser.utils import usertypes
|
||||||
|
|
||||||
|
|
||||||
class InitTests(unittest.TestCase):
|
class InitTests(unittest.TestCase):
|
||||||
@ -36,27 +36,27 @@ class InitTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_empty(self):
|
def test_empty(self):
|
||||||
"""Test constructing an empty NeighborList."""
|
"""Test constructing an empty NeighborList."""
|
||||||
nl = NeighborList()
|
nl = usertypes.NeighborList()
|
||||||
self.assertEqual(nl.items, [])
|
self.assertEqual(nl.items, [])
|
||||||
|
|
||||||
def test_items(self):
|
def test_items(self):
|
||||||
"""Test constructing an NeighborList with items."""
|
"""Test constructing an NeighborList with items."""
|
||||||
nl = NeighborList([1, 2, 3])
|
nl = usertypes.NeighborList([1, 2, 3])
|
||||||
self.assertEqual(nl.items, [1, 2, 3])
|
self.assertEqual(nl.items, [1, 2, 3])
|
||||||
|
|
||||||
def test_len(self):
|
def test_len(self):
|
||||||
"""Test len() on NeighborList."""
|
"""Test len() on NeighborList."""
|
||||||
nl = NeighborList([1, 2, 3])
|
nl = usertypes.NeighborList([1, 2, 3])
|
||||||
self.assertEqual(len(nl), 3)
|
self.assertEqual(len(nl), 3)
|
||||||
|
|
||||||
def test_repr(self):
|
def test_repr(self):
|
||||||
"""Test repr() on NeighborList."""
|
"""Test repr() on NeighborList."""
|
||||||
nl = NeighborList([1, 2, 3])
|
nl = usertypes.NeighborList([1, 2, 3])
|
||||||
self.assertEqual(repr(nl), 'NeighborList([1, 2, 3])')
|
self.assertEqual(repr(nl), 'NeighborList([1, 2, 3])')
|
||||||
|
|
||||||
def test_contains(self):
|
def test_contains(self):
|
||||||
"""Test 'in' on NeighborList."""
|
"""Test 'in' on NeighborList."""
|
||||||
nl = NeighborList([1, 2, 3])
|
nl = usertypes.NeighborList([1, 2, 3])
|
||||||
self.assertIn(2, nl)
|
self.assertIn(2, nl)
|
||||||
self.assertNotIn(4, nl)
|
self.assertNotIn(4, nl)
|
||||||
|
|
||||||
@ -71,17 +71,17 @@ class DefaultTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_simple(self):
|
def test_simple(self):
|
||||||
"""Test default with a numeric argument."""
|
"""Test default with a numeric argument."""
|
||||||
nl = NeighborList([1, 2, 3], default=2)
|
nl = usertypes.NeighborList([1, 2, 3], default=2)
|
||||||
self.assertEqual(nl.idx, 1)
|
self.assertEqual(nl.idx, 1)
|
||||||
|
|
||||||
def test_none(self):
|
def test_none(self):
|
||||||
"""Test default 'None'."""
|
"""Test default 'None'."""
|
||||||
nl = NeighborList([1, 2, None], default=None)
|
nl = usertypes.NeighborList([1, 2, None], default=None)
|
||||||
self.assertEqual(nl.idx, 2)
|
self.assertEqual(nl.idx, 2)
|
||||||
|
|
||||||
def test_unset(self):
|
def test_unset(self):
|
||||||
"""Test unset default value."""
|
"""Test unset default value."""
|
||||||
nl = NeighborList([1, 2, 3])
|
nl = usertypes.NeighborList([1, 2, 3])
|
||||||
self.assertIsNone(nl.idx)
|
self.assertIsNone(nl.idx)
|
||||||
|
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ class EmptyTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.nl = NeighborList()
|
self.nl = usertypes.NeighborList()
|
||||||
|
|
||||||
def test_curitem(self):
|
def test_curitem(self):
|
||||||
"""Test curitem with no item."""
|
"""Test curitem with no item."""
|
||||||
@ -126,7 +126,7 @@ class ItemTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.nl = NeighborList([1, 2, 3, 4, 5], default=3)
|
self.nl = usertypes.NeighborList([1, 2, 3, 4, 5], default=3)
|
||||||
|
|
||||||
def test_curitem(self):
|
def test_curitem(self):
|
||||||
"""Test curitem()."""
|
"""Test curitem()."""
|
||||||
@ -183,11 +183,11 @@ class OneTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.nl = NeighborList([1], default=1)
|
self.nl = usertypes.NeighborList([1], default=1)
|
||||||
|
|
||||||
def test_first_wrap(self):
|
def test_first_wrap(self):
|
||||||
"""Test out of bounds previtem() with mode=wrap."""
|
"""Test out of bounds previtem() with mode=wrap."""
|
||||||
self.nl._mode = NeighborList.Modes.wrap
|
self.nl._mode = usertypes.NeighborList.Modes.wrap
|
||||||
self.nl.firstitem()
|
self.nl.firstitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
self.assertEqual(self.nl.previtem(), 1)
|
self.assertEqual(self.nl.previtem(), 1)
|
||||||
@ -195,7 +195,7 @@ class OneTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_first_block(self):
|
def test_first_block(self):
|
||||||
"""Test out of bounds previtem() with mode=block."""
|
"""Test out of bounds previtem() with mode=block."""
|
||||||
self.nl._mode = NeighborList.Modes.block
|
self.nl._mode = usertypes.NeighborList.Modes.block
|
||||||
self.nl.firstitem()
|
self.nl.firstitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
self.assertEqual(self.nl.previtem(), 1)
|
self.assertEqual(self.nl.previtem(), 1)
|
||||||
@ -203,7 +203,7 @@ class OneTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_first_raise(self):
|
def test_first_raise(self):
|
||||||
"""Test out of bounds previtem() with mode=raise."""
|
"""Test out of bounds previtem() with mode=raise."""
|
||||||
self.nl._mode = NeighborList.Modes.exception
|
self.nl._mode = usertypes.NeighborList.Modes.exception
|
||||||
self.nl.firstitem()
|
self.nl.firstitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
@ -212,7 +212,7 @@ class OneTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_last_wrap(self):
|
def test_last_wrap(self):
|
||||||
"""Test out of bounds nextitem() with mode=wrap."""
|
"""Test out of bounds nextitem() with mode=wrap."""
|
||||||
self.nl._mode = NeighborList.Modes.wrap
|
self.nl._mode = usertypes.NeighborList.Modes.wrap
|
||||||
self.nl.lastitem()
|
self.nl.lastitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
self.assertEqual(self.nl.nextitem(), 1)
|
self.assertEqual(self.nl.nextitem(), 1)
|
||||||
@ -220,7 +220,7 @@ class OneTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_last_block(self):
|
def test_last_block(self):
|
||||||
"""Test out of bounds nextitem() with mode=block."""
|
"""Test out of bounds nextitem() with mode=block."""
|
||||||
self.nl._mode = NeighborList.Modes.block
|
self.nl._mode = usertypes.NeighborList.Modes.block
|
||||||
self.nl.lastitem()
|
self.nl.lastitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
self.assertEqual(self.nl.nextitem(), 1)
|
self.assertEqual(self.nl.nextitem(), 1)
|
||||||
@ -228,7 +228,7 @@ class OneTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_last_raise(self):
|
def test_last_raise(self):
|
||||||
"""Test out of bounds nextitem() with mode=raise."""
|
"""Test out of bounds nextitem() with mode=raise."""
|
||||||
self.nl._mode = NeighborList.Modes.exception
|
self.nl._mode = usertypes.NeighborList.Modes.exception
|
||||||
self.nl.lastitem()
|
self.nl.lastitem()
|
||||||
self.assertEqual(self.nl.idx, 0)
|
self.assertEqual(self.nl.idx, 0)
|
||||||
with self.assertRaises(IndexError):
|
with self.assertRaises(IndexError):
|
||||||
@ -245,8 +245,9 @@ class BlockTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
|
self.nl = usertypes.NeighborList(
|
||||||
mode=NeighborList.Modes.block)
|
[1, 2, 3, 4, 5], default=3,
|
||||||
|
mode=usertypes.NeighborList.Modes.block)
|
||||||
|
|
||||||
def test_first(self):
|
def test_first(self):
|
||||||
"""Test ouf of bounds previtem()."""
|
"""Test ouf of bounds previtem()."""
|
||||||
@ -272,8 +273,8 @@ class WrapTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
|
self.nl = usertypes.NeighborList(
|
||||||
mode=NeighborList.Modes.wrap)
|
[1, 2, 3, 4, 5], default=3, mode=usertypes.NeighborList.Modes.wrap)
|
||||||
|
|
||||||
def test_first(self):
|
def test_first(self):
|
||||||
"""Test ouf of bounds previtem()."""
|
"""Test ouf of bounds previtem()."""
|
||||||
@ -299,8 +300,9 @@ class RaiseTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.nl = NeighborList([1, 2, 3, 4, 5], default=3,
|
self.nl = usertypes.NeighborList(
|
||||||
mode=NeighborList.Modes.exception)
|
[1, 2, 3, 4, 5], default=3,
|
||||||
|
mode=usertypes.NeighborList.Modes.exception)
|
||||||
|
|
||||||
def test_first(self):
|
def test_first(self):
|
||||||
"""Test ouf of bounds previtem()."""
|
"""Test ouf of bounds previtem()."""
|
||||||
@ -328,7 +330,7 @@ class SnapInTests(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.nl = NeighborList([20, 9, 1, 5])
|
self.nl = usertypes.NeighborList([20, 9, 1, 5])
|
||||||
|
|
||||||
def test_bigger(self):
|
def test_bigger(self):
|
||||||
"""Test fuzzyval with snapping to a bigger value."""
|
"""Test fuzzyval with snapping to a bigger value."""
|
||||||
|
@ -21,15 +21,12 @@
|
|||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
|
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config, configdata
|
||||||
import qutebrowser.config.configdata as configdata
|
from qutebrowser.commands import utils as cmdutils
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.log import completion as logger
|
from qutebrowser.utils.log import completion as logger
|
||||||
|
from qutebrowser.models import completion as models
|
||||||
from qutebrowser.models.completionfilter import CompletionFilterModel as CFM
|
from qutebrowser.models.completionfilter import CompletionFilterModel as CFM
|
||||||
from qutebrowser.models.completion import (
|
|
||||||
CommandCompletionModel, SettingSectionCompletionModel,
|
|
||||||
SettingOptionCompletionModel, SettingValueCompletionModel)
|
|
||||||
from qutebrowser.utils.usertypes import Completion
|
|
||||||
|
|
||||||
|
|
||||||
class Completer(QObject):
|
class Completer(QObject):
|
||||||
@ -58,31 +55,32 @@ class Completer(QObject):
|
|||||||
self.ignore_change = False
|
self.ignore_change = False
|
||||||
|
|
||||||
self._models = {
|
self._models = {
|
||||||
Completion.option: {},
|
usertypes.Completion.option: {},
|
||||||
Completion.value: {},
|
usertypes.Completion.value: {},
|
||||||
}
|
}
|
||||||
self._init_command_completion()
|
self._init_command_completion()
|
||||||
self._init_setting_completions()
|
self._init_setting_completions()
|
||||||
|
|
||||||
def _init_command_completion(self):
|
def _init_command_completion(self):
|
||||||
"""Initialize the command completion model."""
|
"""Initialize the command completion model."""
|
||||||
self._models[Completion.command] = CFM(
|
self._models[usertypes.Completion.command] = CFM(
|
||||||
CommandCompletionModel(self), self)
|
models.CommandCompletionModel(self), self)
|
||||||
|
|
||||||
def _init_setting_completions(self):
|
def _init_setting_completions(self):
|
||||||
"""Initialize setting completion models."""
|
"""Initialize setting completion models."""
|
||||||
self._models[Completion.section] = CFM(
|
self._models[usertypes.Completion.section] = CFM(
|
||||||
SettingSectionCompletionModel(self), self)
|
models.SettingSectionCompletionModel(self), self)
|
||||||
self._models[Completion.option] = {}
|
self._models[usertypes.Completion.option] = {}
|
||||||
self._models[Completion.value] = {}
|
self._models[usertypes.Completion.value] = {}
|
||||||
for sectname in configdata.DATA:
|
for sectname in configdata.DATA:
|
||||||
model = SettingOptionCompletionModel(sectname, self)
|
model = models.SettingOptionCompletionModel(sectname, self)
|
||||||
self._models[Completion.option][sectname] = CFM(model, self)
|
self._models[usertypes.Completion.option][sectname] = CFM(
|
||||||
|
model, self)
|
||||||
config.instance().changed.connect(model.on_config_changed)
|
config.instance().changed.connect(model.on_config_changed)
|
||||||
self._models[Completion.value][sectname] = {}
|
self._models[usertypes.Completion.value][sectname] = {}
|
||||||
for opt in configdata.DATA[sectname].keys():
|
for opt in configdata.DATA[sectname].keys():
|
||||||
model = SettingValueCompletionModel(sectname, opt, self)
|
model = models.SettingValueCompletionModel(sectname, opt, self)
|
||||||
self._models[Completion.value][sectname][opt] = CFM(
|
self._models[usertypes.Completion.value][sectname][opt] = CFM(
|
||||||
model, self)
|
model, self)
|
||||||
config.instance().changed.connect(model.on_config_changed)
|
config.instance().changed.connect(model.on_config_changed)
|
||||||
|
|
||||||
@ -95,7 +93,7 @@ class Completer(QObject):
|
|||||||
"""
|
"""
|
||||||
if cursor_part == 0:
|
if cursor_part == 0:
|
||||||
# '|' or 'set|'
|
# '|' or 'set|'
|
||||||
return self._models[Completion.command]
|
return self._models[usertypes.Completion.command]
|
||||||
# delegate completion to command
|
# delegate completion to command
|
||||||
try:
|
try:
|
||||||
completions = cmdutils.cmd_dict[parts[0]].completion
|
completions = cmdutils.cmd_dict[parts[0]].completion
|
||||||
@ -115,10 +113,10 @@ class Completer(QObject):
|
|||||||
return None
|
return None
|
||||||
dbg_completions[idx] = '*' + dbg_completions[idx] + '*'
|
dbg_completions[idx] = '*' + dbg_completions[idx] + '*'
|
||||||
logger.debug("completions: {}".format(', '.join(dbg_completions)))
|
logger.debug("completions: {}".format(', '.join(dbg_completions)))
|
||||||
if completion == Completion.option:
|
if completion == usertypes.Completion.option:
|
||||||
section = parts[cursor_part - 1]
|
section = parts[cursor_part - 1]
|
||||||
model = self._models[completion].get(section)
|
model = self._models[completion].get(section)
|
||||||
elif completion == Completion.value:
|
elif completion == usertypes.Completion.value:
|
||||||
section = parts[cursor_part - 2]
|
section = parts[cursor_part - 2]
|
||||||
option = parts[cursor_part - 1]
|
option = parts[cursor_part - 1]
|
||||||
try:
|
try:
|
||||||
|
@ -23,13 +23,13 @@ import re
|
|||||||
import pdb
|
import pdb
|
||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
from functools import wraps
|
import functools
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtRemoveInputHook, QEvent, QCoreApplication
|
from PyQt5.QtCore import pyqtRemoveInputHook, QEvent, QCoreApplication
|
||||||
|
|
||||||
from qutebrowser.utils.misc import elide, compact_text
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.log import misc as logger
|
from qutebrowser.utils.log import misc as logger
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import utils as cmdutils
|
||||||
|
|
||||||
|
|
||||||
@cmdutils.register(debug=True, name='debug-set-trace')
|
@cmdutils.register(debug=True, name='debug-set-trace')
|
||||||
@ -89,7 +89,7 @@ def log_events(klass):
|
|||||||
"""Class decorator to log Qt events."""
|
"""Class decorator to log Qt events."""
|
||||||
old_event = klass.event
|
old_event = klass.event
|
||||||
|
|
||||||
@wraps(old_event)
|
@functools.wraps(old_event)
|
||||||
def new_event(self, e, *args, **kwargs):
|
def new_event(self, e, *args, **kwargs):
|
||||||
"""Wrapper for event() which logs events."""
|
"""Wrapper for event() which logs events."""
|
||||||
logger.debug("Event in {}: {}".format(klass.__name__,
|
logger.debug("Event in {}: {}".format(klass.__name__,
|
||||||
@ -115,7 +115,7 @@ def trace_lines(do_trace):
|
|||||||
if sys is not None:
|
if sys is not None:
|
||||||
loc = '{}:{}'.format(frame.f_code.co_filename, frame.f_lineno)
|
loc = '{}:{}'.format(frame.f_code.co_filename, frame.f_lineno)
|
||||||
if arg is not None:
|
if arg is not None:
|
||||||
arg = compact_text(str(arg), 200)
|
arg = utils.compact_text(str(arg), 200)
|
||||||
else:
|
else:
|
||||||
arg = ''
|
arg = ''
|
||||||
print("{:11} {:80} {}".format(event, loc, arg), file=sys.stderr)
|
print("{:11} {:80} {}".format(event, loc, arg), file=sys.stderr)
|
||||||
@ -228,5 +228,6 @@ def dbg_signal(sig, args):
|
|||||||
Return:
|
Return:
|
||||||
A human-readable string representation of signal/args.
|
A human-readable string representation of signal/args.
|
||||||
"""
|
"""
|
||||||
argstr = ', '.join([elide(str(a).replace('\n', ' '), 20) for a in args])
|
argstr = ', '.join([utils.elide(str(a).replace('\n', ' '), 20)
|
||||||
|
for a in args])
|
||||||
return '{}({})'.format(signal_name(sig), argstr)
|
return '{}({})'.format(signal_name(sig), argstr)
|
||||||
|
@ -26,9 +26,9 @@ import faulthandler
|
|||||||
import traceback
|
import traceback
|
||||||
import signal
|
import signal
|
||||||
try:
|
try:
|
||||||
from tkinter import Tk, messagebox # pylint: disable=import-error
|
import tkinter # pylint: disable=import-error
|
||||||
except ImportError:
|
except ImportError:
|
||||||
Tk = None
|
tkinter = None
|
||||||
|
|
||||||
|
|
||||||
def _missing_str(name, debian=None, arch=None, windows=None, pip=None):
|
def _missing_str(name, debian=None, arch=None, windows=None, pip=None):
|
||||||
@ -186,10 +186,10 @@ def check_pyqt_core():
|
|||||||
text = text.replace('<b>', '')
|
text = text.replace('<b>', '')
|
||||||
text = text.replace('</b>', '')
|
text = text.replace('</b>', '')
|
||||||
text = text.replace('<br />', '\n')
|
text = text.replace('<br />', '\n')
|
||||||
if Tk:
|
if tkinter:
|
||||||
root = Tk()
|
root = tkinter.Tk()
|
||||||
root.withdraw()
|
root.withdraw()
|
||||||
messagebox.showerror("qutebrowser: Fatal error!", text)
|
tkinter.messagebox.showerror("qutebrowser: Fatal error!", text)
|
||||||
else:
|
else:
|
||||||
print(text, file=sys.stderr)
|
print(text, file=sys.stderr)
|
||||||
if '--debug' in sys.argv:
|
if '--debug' in sys.argv:
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
"""Launcher for an external editor."""
|
"""Launcher for an external editor."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from tempfile import mkstemp
|
import tempfile
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, QProcess, QObject
|
from PyQt5.QtCore import pyqtSignal, QProcess, QObject
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.utils import message
|
||||||
from qutebrowser.utils.log import procs as logger
|
from qutebrowser.utils.log import procs as logger
|
||||||
|
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ class ExternalEditor(QObject):
|
|||||||
if self.text is not None:
|
if self.text is not None:
|
||||||
raise ValueError("Already editing a file!")
|
raise ValueError("Already editing a file!")
|
||||||
self.text = text
|
self.text = text
|
||||||
self.oshandle, self.filename = mkstemp(text=True)
|
self.oshandle, self.filename = tempfile.mkstemp(text=True)
|
||||||
if text:
|
if text:
|
||||||
encoding = config.get('general', 'editor-encoding')
|
encoding = config.get('general', 'editor-encoding')
|
||||||
with open(self.filename, 'w', encoding=encoding) as f:
|
with open(self.filename, 'w', encoding=encoding) as f:
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
import qutebrowser.utils.rfc6266 as rfc6266
|
from qutebrowser.utils import rfc6266
|
||||||
from qutebrowser.utils.log import misc as logger
|
from qutebrowser.utils.log import misc as logger
|
||||||
|
|
||||||
from PyQt5.QtNetwork import QNetworkRequest
|
from PyQt5.QtNetwork import QNetworkRequest
|
||||||
|
@ -24,9 +24,8 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import html as pyhtml
|
import html as pyhtml
|
||||||
import logging
|
import logging
|
||||||
from contextlib import contextmanager
|
import contextlib
|
||||||
from logging import getLogger
|
import collections
|
||||||
from collections import deque
|
|
||||||
|
|
||||||
from PyQt5.QtCore import (QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg,
|
from PyQt5.QtCore import (QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg,
|
||||||
qInstallMessageHandler)
|
qInstallMessageHandler)
|
||||||
@ -38,9 +37,9 @@ except ImportError:
|
|||||||
colorama = None
|
colorama = None
|
||||||
try:
|
try:
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
from colorlog import ColoredFormatter
|
import colorlog
|
||||||
except ImportError:
|
except ImportError:
|
||||||
ColoredFormatter = None
|
colorlog = None
|
||||||
else:
|
else:
|
||||||
# colorlog calls colorama.init() which we don't want, also it breaks our
|
# colorlog calls colorama.init() which we don't want, also it breaks our
|
||||||
# sys.stdout/sys.stderr if they are None. Bugreports:
|
# sys.stdout/sys.stderr if they are None. Bugreports:
|
||||||
@ -81,25 +80,25 @@ LOG_COLORS = {
|
|||||||
|
|
||||||
# The different loggers used.
|
# The different loggers used.
|
||||||
|
|
||||||
statusbar = getLogger('statusbar')
|
statusbar = logging.getLogger('statusbar')
|
||||||
completion = getLogger('completion')
|
completion = logging.getLogger('completion')
|
||||||
destroy = getLogger('destroy')
|
destroy = logging.getLogger('destroy')
|
||||||
modes = getLogger('modes')
|
modes = logging.getLogger('modes')
|
||||||
webview = getLogger('webview')
|
webview = logging.getLogger('webview')
|
||||||
mouse = getLogger('mouse')
|
mouse = logging.getLogger('mouse')
|
||||||
misc = getLogger('misc')
|
misc = logging.getLogger('misc')
|
||||||
url = getLogger('url')
|
url = logging.getLogger('url')
|
||||||
procs = getLogger('procs')
|
procs = logging.getLogger('procs')
|
||||||
commands = getLogger('commands')
|
commands = logging.getLogger('commands')
|
||||||
init = getLogger('init')
|
init = logging.getLogger('init')
|
||||||
signals = getLogger('signals')
|
signals = logging.getLogger('signals')
|
||||||
hints = getLogger('hints')
|
hints = logging.getLogger('hints')
|
||||||
keyboard = getLogger('keyboard')
|
keyboard = logging.getLogger('keyboard')
|
||||||
downloads = getLogger('downloads')
|
downloads = logging.getLogger('downloads')
|
||||||
js = getLogger('js') # Javascript console messages
|
js = logging.getLogger('js') # Javascript console messages
|
||||||
qt = getLogger('qt') # Warnings produced by Qt
|
qt = logging.getLogger('qt') # Warnings produced by Qt
|
||||||
style = getLogger('style')
|
style = logging.getLogger('style')
|
||||||
rfc6266 = getLogger('rfc6266')
|
rfc6266 = logging.getLogger('rfc6266')
|
||||||
|
|
||||||
|
|
||||||
ram_handler = None
|
ram_handler = None
|
||||||
@ -114,7 +113,7 @@ def init_log(args):
|
|||||||
raise ValueError("Invalid log level: {}".format(args.loglevel))
|
raise ValueError("Invalid log level: {}".format(args.loglevel))
|
||||||
|
|
||||||
console, ram = _init_handlers(numeric_level, args.color, args.loglines)
|
console, ram = _init_handlers(numeric_level, args.color, args.loglines)
|
||||||
root = getLogger()
|
root = logging.getLogger()
|
||||||
if console is not None:
|
if console is not None:
|
||||||
if args.logfilter is not None:
|
if args.logfilter is not None:
|
||||||
console.addFilter(LogFilter(args.logfilter.split(',')))
|
console.addFilter(LogFilter(args.logfilter.split(',')))
|
||||||
@ -126,7 +125,7 @@ def init_log(args):
|
|||||||
qInstallMessageHandler(qt_message_handler)
|
qInstallMessageHandler(qt_message_handler)
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextlib.contextmanager
|
||||||
def disable_qt_msghandler():
|
def disable_qt_msghandler():
|
||||||
"""Contextmanager which temporarely disables the Qt message handler."""
|
"""Contextmanager which temporarely disables the Qt message handler."""
|
||||||
old_handler = qInstallMessageHandler(None)
|
old_handler = qInstallMessageHandler(None)
|
||||||
@ -191,10 +190,10 @@ def _init_formatters(level, color):
|
|||||||
if sys.stderr is None:
|
if sys.stderr is None:
|
||||||
return None, ram_formatter, html_formatter, False
|
return None, ram_formatter, html_formatter, False
|
||||||
use_colorama = False
|
use_colorama = False
|
||||||
if (ColoredFormatter is not None and (os.name == 'posix' or colorama) and
|
if (colorlog is not None and (os.name == 'posix' or colorama) and
|
||||||
sys.stderr.isatty() and color):
|
sys.stderr.isatty() and color):
|
||||||
console_formatter = ColoredFormatter(console_fmt_colored, DATEFMT,
|
console_formatter = colorlog.ColoredFormatter(
|
||||||
log_colors=LOG_COLORS)
|
console_fmt_colored, DATEFMT, log_colors=LOG_COLORS)
|
||||||
if colorama:
|
if colorama:
|
||||||
use_colorama = True
|
use_colorama = True
|
||||||
else:
|
else:
|
||||||
@ -310,9 +309,9 @@ class RAMHandler(logging.Handler):
|
|||||||
super().__init__()
|
super().__init__()
|
||||||
self.html_formatter = None
|
self.html_formatter = None
|
||||||
if capacity != -1:
|
if capacity != -1:
|
||||||
self.data = deque(maxlen=capacity)
|
self.data = collections.deque(maxlen=capacity)
|
||||||
else:
|
else:
|
||||||
self.data = deque()
|
self.data = collections.deque()
|
||||||
|
|
||||||
def emit(self, record):
|
def emit(self, record):
|
||||||
self.data.append(record)
|
self.data.append(record)
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, QCoreApplication, QObject, QTimer
|
from PyQt5.QtCore import pyqtSignal, QCoreApplication, QObject, QTimer
|
||||||
|
|
||||||
from qutebrowser.utils.usertypes import PromptMode, Question
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.log import misc as logger
|
from qutebrowser.utils.log import misc as logger
|
||||||
|
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ def ask(message, mode, default=None):
|
|||||||
Return:
|
Return:
|
||||||
The answer the user gave or None if the prompt was cancelled.
|
The answer the user gave or None if the prompt was cancelled.
|
||||||
"""
|
"""
|
||||||
q = Question()
|
q = usertypes.Question()
|
||||||
q.text = message
|
q.text = message
|
||||||
q.mode = mode
|
q.mode = mode
|
||||||
q.default = default
|
q.default = default
|
||||||
@ -75,9 +75,9 @@ def ask(message, mode, default=None):
|
|||||||
|
|
||||||
def alert(message):
|
def alert(message):
|
||||||
"""Display an alert which needs to be confirmed."""
|
"""Display an alert which needs to be confirmed."""
|
||||||
q = Question()
|
q = usertypes.Question()
|
||||||
q.text = message
|
q.text = message
|
||||||
q.mode = PromptMode.alert
|
q.mode = usertypes.PromptMode.alert
|
||||||
instance().ask(q, blocking=True)
|
instance().ask(q, blocking=True)
|
||||||
q.deleteLater()
|
q.deleteLater()
|
||||||
|
|
||||||
@ -91,10 +91,10 @@ def ask_async(message, mode, handler, default=None):
|
|||||||
handler: The function to get called with the answer as argument.
|
handler: The function to get called with the answer as argument.
|
||||||
default: The default value to display.
|
default: The default value to display.
|
||||||
"""
|
"""
|
||||||
if not isinstance(mode, PromptMode):
|
if not isinstance(mode, usertypes.PromptMode):
|
||||||
raise TypeError("Mode {} is no PromptMode member!".format(mode))
|
raise TypeError("Mode {} is no PromptMode member!".format(mode))
|
||||||
bridge = instance()
|
bridge = instance()
|
||||||
q = Question(bridge)
|
q = usertypes.Question(bridge)
|
||||||
q.text = message
|
q.text = message
|
||||||
q.mode = mode
|
q.mode = mode
|
||||||
q.default = default
|
q.default = default
|
||||||
@ -113,9 +113,9 @@ def confirm_async(message, yes_action, no_action=None, default=None):
|
|||||||
default: True/False to set a default value, or None.
|
default: True/False to set a default value, or None.
|
||||||
"""
|
"""
|
||||||
bridge = instance()
|
bridge = instance()
|
||||||
q = Question(bridge)
|
q = usertypes.Question(bridge)
|
||||||
q.text = message
|
q.text = message
|
||||||
q.mode = PromptMode.yesno
|
q.mode = usertypes.PromptMode.yesno
|
||||||
q.default = default
|
q.default = default
|
||||||
q.answered_yes.connect(yes_action)
|
q.answered_yes.connect(yes_action)
|
||||||
if no_action is not None:
|
if no_action is not None:
|
||||||
@ -152,7 +152,7 @@ class MessageBridge(QObject):
|
|||||||
s_info = pyqtSignal(str, bool)
|
s_info = pyqtSignal(str, bool)
|
||||||
s_set_text = pyqtSignal(str)
|
s_set_text = pyqtSignal(str)
|
||||||
s_set_cmd_text = pyqtSignal(str)
|
s_set_cmd_text = pyqtSignal(str)
|
||||||
s_question = pyqtSignal(Question, bool)
|
s_question = pyqtSignal(usertypes.Question, bool)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<{}>'.format(self.__class__.__name__)
|
return '<{}>'.format(self.__class__.__name__)
|
||||||
|
@ -25,17 +25,17 @@ import sys
|
|||||||
import shlex
|
import shlex
|
||||||
import os.path
|
import os.path
|
||||||
import urllib.request
|
import urllib.request
|
||||||
from urllib.parse import urljoin, urlencode
|
import urllib.parse
|
||||||
from collections import OrderedDict
|
import collections
|
||||||
from functools import reduce
|
import functools
|
||||||
from contextlib import contextmanager
|
import contextlib
|
||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication, QStandardPaths, Qt
|
from PyQt5.QtCore import QCoreApplication, QStandardPaths, Qt
|
||||||
from PyQt5.QtGui import QKeySequence, QColor
|
from PyQt5.QtGui import QKeySequence, QColor
|
||||||
from pkg_resources import resource_string
|
import pkg_resources
|
||||||
|
|
||||||
import qutebrowser
|
import qutebrowser
|
||||||
from qutebrowser.utils.qt import qt_version_check, qt_ensure_valid
|
from qutebrowser.utils import qt as qtutils
|
||||||
|
|
||||||
|
|
||||||
def elide(text, length):
|
def elide(text, length):
|
||||||
@ -81,7 +81,8 @@ def read_file(filename):
|
|||||||
with open(fn, 'r', encoding='utf-8') as f:
|
with open(fn, 'r', encoding='utf-8') as f:
|
||||||
return f.read()
|
return f.read()
|
||||||
else:
|
else:
|
||||||
return resource_string(qutebrowser.__name__, filename).decode('UTF-8')
|
data = pkg_resources.resource_string(qutebrowser.__name__, filename)
|
||||||
|
return data.decode('UTF-8')
|
||||||
|
|
||||||
|
|
||||||
def dotted_getattr(obj, path):
|
def dotted_getattr(obj, path):
|
||||||
@ -94,7 +95,7 @@ def dotted_getattr(obj, path):
|
|||||||
Return:
|
Return:
|
||||||
The object at path.
|
The object at path.
|
||||||
"""
|
"""
|
||||||
return reduce(getattr, path.split('.'), obj)
|
return functools.reduce(getattr, path.split('.'), obj)
|
||||||
|
|
||||||
|
|
||||||
def safe_shlex_split(s):
|
def safe_shlex_split(s):
|
||||||
@ -134,8 +135,8 @@ def pastebin(text):
|
|||||||
'title': "qutebrowser crash",
|
'title': "qutebrowser crash",
|
||||||
'name': "qutebrowser",
|
'name': "qutebrowser",
|
||||||
}
|
}
|
||||||
encoded_data = urlencode(data).encode('utf-8')
|
encoded_data = urllib.parse.urlencode(data).encode('utf-8')
|
||||||
create_url = urljoin(api_url, 'create')
|
create_url = urllib.parse.urljoin(api_url, 'create')
|
||||||
headers = {
|
headers = {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
|
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
|
||||||
}
|
}
|
||||||
@ -189,7 +190,7 @@ def actute_warning():
|
|||||||
return
|
return
|
||||||
# Qt >= 5.3 doesn't seem to be affected
|
# Qt >= 5.3 doesn't seem to be affected
|
||||||
try:
|
try:
|
||||||
if qt_version_check('5.3.0'):
|
if qtutils.qt_version_check('5.3.0'):
|
||||||
return
|
return
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
@ -246,8 +247,8 @@ def interpolate_color(start, end, percent, colorspace=QColor.Rgb):
|
|||||||
Raise:
|
Raise:
|
||||||
ValueError if invalid parameters are passed.
|
ValueError if invalid parameters are passed.
|
||||||
"""
|
"""
|
||||||
qt_ensure_valid(start)
|
qtutils.qt_ensure_valid(start)
|
||||||
qt_ensure_valid(end)
|
qtutils.qt_ensure_valid(end)
|
||||||
out = QColor()
|
out = QColor()
|
||||||
if colorspace == QColor.Rgb:
|
if colorspace == QColor.Rgb:
|
||||||
a_c1, a_c2, a_c3, _alpha = start.getRgb()
|
a_c1, a_c2, a_c3, _alpha = start.getRgb()
|
||||||
@ -270,7 +271,7 @@ def interpolate_color(start, end, percent, colorspace=QColor.Rgb):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Invalid colorspace!")
|
raise ValueError("Invalid colorspace!")
|
||||||
out = out.convertTo(start.spec())
|
out = out.convertTo(start.spec())
|
||||||
qt_ensure_valid(out)
|
qtutils.qt_ensure_valid(out)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
@ -400,7 +401,7 @@ def keyevent_to_string(e):
|
|||||||
A name of the key (combination) as a string or
|
A name of the key (combination) as a string or
|
||||||
None if only modifiers are pressed..
|
None if only modifiers are pressed..
|
||||||
"""
|
"""
|
||||||
modmask2str = OrderedDict([
|
modmask2str = collections.OrderedDict([
|
||||||
(Qt.ControlModifier, 'Ctrl'),
|
(Qt.ControlModifier, 'Ctrl'),
|
||||||
(Qt.AltModifier, 'Alt'),
|
(Qt.AltModifier, 'Alt'),
|
||||||
(Qt.MetaModifier, 'Meta'),
|
(Qt.MetaModifier, 'Meta'),
|
||||||
@ -460,7 +461,7 @@ class FakeIOStream(io.TextIOBase):
|
|||||||
return super().isatty()
|
return super().isatty()
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextlib.contextmanager
|
||||||
def fake_io(write_func):
|
def fake_io(write_func):
|
||||||
"""Run code with stdout and stderr replaced by FakeIOStreams.
|
"""Run code with stdout and stderr replaced by FakeIOStreams.
|
||||||
|
|
||||||
@ -482,7 +483,7 @@ def fake_io(write_func):
|
|||||||
sys.stderr = old_stderr
|
sys.stderr = old_stderr
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextlib.contextmanager
|
||||||
def disabled_excepthook():
|
def disabled_excepthook():
|
||||||
"""Run code with the exception hook temporarely disabled."""
|
"""Run code with the exception hook temporarely disabled."""
|
||||||
old_excepthook = sys.excepthook
|
old_excepthook = sys.excepthook
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
|
|
||||||
from PyQt5.QtWidgets import QApplication, QLineEdit
|
from PyQt5.QtWidgets import QApplication, QLineEdit
|
||||||
|
|
||||||
import qutebrowser.commands.utils as cmd
|
from qutebrowser.commands import utils as cmdutils
|
||||||
from qutebrowser.utils.usertypes import KeyMode
|
from qutebrowser.utils import usertypes as typ
|
||||||
|
|
||||||
|
|
||||||
class ReadlineBridge:
|
class ReadlineBridge:
|
||||||
@ -45,8 +45,8 @@ class ReadlineBridge:
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_backward_char(self):
|
def rl_backward_char(self):
|
||||||
"""Move back a character.
|
"""Move back a character.
|
||||||
|
|
||||||
@ -56,8 +56,8 @@ class ReadlineBridge:
|
|||||||
return
|
return
|
||||||
self.widget.cursorBackward(False)
|
self.widget.cursorBackward(False)
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_forward_char(self):
|
def rl_forward_char(self):
|
||||||
"""Move forward a character.
|
"""Move forward a character.
|
||||||
|
|
||||||
@ -67,8 +67,8 @@ class ReadlineBridge:
|
|||||||
return
|
return
|
||||||
self.widget.cursorForward(False)
|
self.widget.cursorForward(False)
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_backward_word(self):
|
def rl_backward_word(self):
|
||||||
"""Move back to the start of the current or previous word.
|
"""Move back to the start of the current or previous word.
|
||||||
|
|
||||||
@ -78,8 +78,8 @@ class ReadlineBridge:
|
|||||||
return
|
return
|
||||||
self.widget.cursorWordBackward(False)
|
self.widget.cursorWordBackward(False)
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_forward_word(self):
|
def rl_forward_word(self):
|
||||||
"""Move forward to the end of the next word.
|
"""Move forward to the end of the next word.
|
||||||
|
|
||||||
@ -89,8 +89,8 @@ class ReadlineBridge:
|
|||||||
return
|
return
|
||||||
self.widget.cursorWordForward(False)
|
self.widget.cursorWordForward(False)
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_beginning_of_line(self):
|
def rl_beginning_of_line(self):
|
||||||
"""Move to the start of the line.
|
"""Move to the start of the line.
|
||||||
|
|
||||||
@ -100,8 +100,8 @@ class ReadlineBridge:
|
|||||||
return
|
return
|
||||||
self.widget.home(False)
|
self.widget.home(False)
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_end_of_line(self):
|
def rl_end_of_line(self):
|
||||||
"""Move to the end of the line.
|
"""Move to the end of the line.
|
||||||
|
|
||||||
@ -111,8 +111,8 @@ class ReadlineBridge:
|
|||||||
return
|
return
|
||||||
self.widget.end(False)
|
self.widget.end(False)
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_unix_line_discard(self):
|
def rl_unix_line_discard(self):
|
||||||
"""Remove chars backward from the cursor to the beginning of the line.
|
"""Remove chars backward from the cursor to the beginning of the line.
|
||||||
|
|
||||||
@ -124,8 +124,8 @@ class ReadlineBridge:
|
|||||||
self.deleted[self.widget] = self.widget.selectedText()
|
self.deleted[self.widget] = self.widget.selectedText()
|
||||||
self.widget.del_()
|
self.widget.del_()
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_kill_line(self):
|
def rl_kill_line(self):
|
||||||
"""Remove chars from the cursor to the end of the line.
|
"""Remove chars from the cursor to the end of the line.
|
||||||
|
|
||||||
@ -137,8 +137,8 @@ class ReadlineBridge:
|
|||||||
self.deleted[self.widget] = self.widget.selectedText()
|
self.deleted[self.widget] = self.widget.selectedText()
|
||||||
self.widget.del_()
|
self.widget.del_()
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_unix_word_rubout(self):
|
def rl_unix_word_rubout(self):
|
||||||
"""Remove chars from the cursor to the beginning of the word.
|
"""Remove chars from the cursor to the beginning of the word.
|
||||||
|
|
||||||
@ -150,8 +150,8 @@ class ReadlineBridge:
|
|||||||
self.deleted[self.widget] = self.widget.selectedText()
|
self.deleted[self.widget] = self.widget.selectedText()
|
||||||
self.widget.del_()
|
self.widget.del_()
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_kill_word(self):
|
def rl_kill_word(self):
|
||||||
"""Remove chars from the cursor to the end of the current word.
|
"""Remove chars from the cursor to the end of the current word.
|
||||||
|
|
||||||
@ -163,8 +163,8 @@ class ReadlineBridge:
|
|||||||
self.deleted[self.widget] = self.widget.selectedText()
|
self.deleted[self.widget] = self.widget.selectedText()
|
||||||
self.widget.del_()
|
self.widget.del_()
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_yank(self):
|
def rl_yank(self):
|
||||||
"""Paste the most recently deleted text.
|
"""Paste the most recently deleted text.
|
||||||
|
|
||||||
@ -174,8 +174,8 @@ class ReadlineBridge:
|
|||||||
return
|
return
|
||||||
self.widget.insert(self.deleted[self.widget])
|
self.widget.insert(self.deleted[self.widget])
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_delete_char(self):
|
def rl_delete_char(self):
|
||||||
"""Delete the character after the cursor.
|
"""Delete the character after the cursor.
|
||||||
|
|
||||||
@ -185,8 +185,8 @@ class ReadlineBridge:
|
|||||||
return
|
return
|
||||||
self.widget.del_()
|
self.widget.del_()
|
||||||
|
|
||||||
@cmd.register(instance='rl_bridge', hide=True,
|
@cmdutils.register(instance='rl_bridge', hide=True,
|
||||||
modes=[KeyMode.command, KeyMode.prompt])
|
modes=[typ.KeyMode.command, typ.KeyMode.prompt])
|
||||||
def rl_backward_delete_char(self):
|
def rl_backward_delete_char(self):
|
||||||
"""Delete the character before the cursor.
|
"""Delete the character before the cursor.
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
"""pyPEG parsing for the RFC 6266 (Content-Disposition) header. """
|
"""pyPEG parsing for the RFC 6266 (Content-Disposition) header. """
|
||||||
|
|
||||||
from collections import namedtuple
|
import collections
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import string
|
import string
|
||||||
import re
|
import re
|
||||||
@ -209,7 +209,7 @@ class ContentDispositionValue:
|
|||||||
peg.optional(';'))
|
peg.optional(';'))
|
||||||
|
|
||||||
|
|
||||||
LangTagged = namedtuple('LangTagged', 'string langtag')
|
LangTagged = collections.namedtuple('LangTagged', 'string langtag')
|
||||||
|
|
||||||
|
|
||||||
class DuplicateParamError(Exception):
|
class DuplicateParamError(Exception):
|
||||||
|
@ -26,9 +26,9 @@ import urllib.parse
|
|||||||
from PyQt5.QtCore import QUrl
|
from PyQt5.QtCore import QUrl
|
||||||
from PyQt5.QtNetwork import QHostInfo
|
from PyQt5.QtNetwork import QHostInfo
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.log import url as logger
|
from qutebrowser.utils.log import url as logger
|
||||||
from qutebrowser.utils.misc import qt_ensure_valid
|
|
||||||
|
|
||||||
|
|
||||||
# FIXME: we probably could raise some exceptions on invalid URLs
|
# FIXME: we probably could raise some exceptions on invalid URLs
|
||||||
@ -65,7 +65,7 @@ def _get_search_url(txt):
|
|||||||
if not term:
|
if not term:
|
||||||
raise FuzzyUrlError("No search term given")
|
raise FuzzyUrlError("No search term given")
|
||||||
url = QUrl.fromUserInput(template.format(urllib.parse.quote(term)))
|
url = QUrl.fromUserInput(template.format(urllib.parse.quote(term)))
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ def fuzzy_url(urlstr):
|
|||||||
url = QUrl.fromUserInput(stripped)
|
url = QUrl.fromUserInput(stripped)
|
||||||
logger.debug("Converting fuzzy term {} to URL -> {}".format(
|
logger.debug("Converting fuzzy term {} to URL -> {}".format(
|
||||||
urlstr, url.toDisplayString()))
|
urlstr, url.toDisplayString()))
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ import enum as pyenum
|
|||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, QObject, QTimer
|
from PyQt5.QtCore import pyqtSignal, QObject, QTimer
|
||||||
|
|
||||||
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.log import misc as logger
|
from qutebrowser.utils.log import misc as logger
|
||||||
from qutebrowser.utils.qt import check_overflow
|
|
||||||
|
|
||||||
|
|
||||||
_UNSET = object()
|
_UNSET = object()
|
||||||
@ -372,13 +372,13 @@ class Timer(QTimer):
|
|||||||
|
|
||||||
def setInterval(self, msec):
|
def setInterval(self, msec):
|
||||||
"""Extend setInterval to check for overflows."""
|
"""Extend setInterval to check for overflows."""
|
||||||
check_overflow(msec, 'int')
|
qtutils.check_overflow(msec, 'int')
|
||||||
super().setInterval(msec)
|
super().setInterval(msec)
|
||||||
|
|
||||||
def start(self, msec=None):
|
def start(self, msec=None):
|
||||||
"""Extend start to check for overflows."""
|
"""Extend start to check for overflows."""
|
||||||
if msec is not None:
|
if msec is not None:
|
||||||
check_overflow(msec, 'int')
|
qtutils.check_overflow(msec, 'int')
|
||||||
super().start(msec)
|
super().start(msec)
|
||||||
else:
|
else:
|
||||||
super().start()
|
super().start()
|
||||||
|
@ -21,10 +21,10 @@
|
|||||||
|
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.usertypes import Timer
|
from qutebrowser.commands import runners
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
from qutebrowser.commands import utils as cmdutils
|
||||||
from qutebrowser.commands.runners import CommandRunner
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
|
|
||||||
|
|
||||||
_timers = []
|
_timers = []
|
||||||
@ -34,7 +34,7 @@ _commandrunner = None
|
|||||||
def init():
|
def init():
|
||||||
"""Initialize the global _commandrunner."""
|
"""Initialize the global _commandrunner."""
|
||||||
global _commandrunner
|
global _commandrunner
|
||||||
_commandrunner = CommandRunner()
|
_commandrunner = runners.CommandRunner()
|
||||||
|
|
||||||
|
|
||||||
@cmdutils.register(nargs=(2, None))
|
@cmdutils.register(nargs=(2, None))
|
||||||
@ -46,15 +46,15 @@ def later(ms, *command):
|
|||||||
command: The command/args to run.
|
command: The command/args to run.
|
||||||
"""
|
"""
|
||||||
ms = int(ms)
|
ms = int(ms)
|
||||||
timer = Timer(name='later')
|
timer = usertypes.Timer(name='later')
|
||||||
timer.setSingleShot(True)
|
timer.setSingleShot(True)
|
||||||
if ms < 0:
|
if ms < 0:
|
||||||
raise CommandError("I can't run something in the past!")
|
raise cmdexc.CommandError("I can't run something in the past!")
|
||||||
try:
|
try:
|
||||||
timer.setInterval(ms)
|
timer.setInterval(ms)
|
||||||
except OverflowError:
|
except OverflowError:
|
||||||
raise CommandError("Numeric argument is too large for internal int "
|
raise cmdexc.CommandError("Numeric argument is too large for internal "
|
||||||
"representation.")
|
"int representation.")
|
||||||
_timers.append(timer)
|
_timers.append(timer)
|
||||||
cmdline = ' '.join(command)
|
cmdline = ' '.join(command)
|
||||||
timer.timeout.connect(partial(_commandrunner.run_safely, cmdline))
|
timer.timeout.connect(partial(_commandrunner.run_safely, cmdline))
|
||||||
|
@ -29,7 +29,7 @@ from PyQt5.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, qVersion
|
|||||||
from PyQt5.QtWebKit import qWebKitVersion
|
from PyQt5.QtWebKit import qWebKitVersion
|
||||||
|
|
||||||
import qutebrowser
|
import qutebrowser
|
||||||
from qutebrowser.utils.misc import read_file
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.log import misc as logger
|
from qutebrowser.utils.log import misc as logger
|
||||||
|
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ def _git_str():
|
|||||||
return commit
|
return commit
|
||||||
# If that fails, check the git-commit-id file.
|
# If that fails, check the git-commit-id file.
|
||||||
try:
|
try:
|
||||||
return read_file('git-commit-id')
|
return utils.read_file('git-commit-id')
|
||||||
except (FileNotFoundError, ImportError):
|
except (FileNotFoundError, ImportError):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -30,13 +30,13 @@ Module attributes:
|
|||||||
from PyQt5.QtCore import QRect, QUrl
|
from PyQt5.QtCore import QRect, QUrl
|
||||||
from PyQt5.QtWebKit import QWebElement
|
from PyQt5.QtWebKit import QWebElement
|
||||||
|
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.config import config
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.utils import log, usertypes
|
||||||
from qutebrowser.utils.usertypes import enum
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.misc import compact_text
|
|
||||||
|
|
||||||
|
|
||||||
Group = enum('Group', 'all', 'links', 'images', 'url', 'prevnext', 'focus')
|
Group = usertypes.enum('Group', 'all', 'links', 'images', 'url', 'prevnext',
|
||||||
|
'focus')
|
||||||
|
|
||||||
|
|
||||||
SELECTORS = {
|
SELECTORS = {
|
||||||
@ -284,4 +284,4 @@ def focus_elem(frame):
|
|||||||
|
|
||||||
def debug_text(elem):
|
def debug_text(elem):
|
||||||
"""Get a text based on an element suitable for debug output."""
|
"""Get a text based on an element suitable for debug output."""
|
||||||
return compact_text(elem.toOuterXml(), 500)
|
return utils.compact_text(elem.toOuterXml(), 500)
|
||||||
|
@ -26,13 +26,11 @@ subclasses to provide completions.
|
|||||||
from PyQt5.QtWidgets import QStyle, QTreeView, QSizePolicy
|
from PyQt5.QtWidgets import QStyle, QTreeView, QSizePolicy
|
||||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QItemSelectionModel
|
from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QItemSelectionModel
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.commands import utils as cmdutils
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.config import config, style
|
||||||
from qutebrowser.widgets.completiondelegate import CompletionItemDelegate
|
from qutebrowser.widgets import completiondelegate
|
||||||
from qutebrowser.config.style import set_register_stylesheet
|
from qutebrowser.utils import completer, usertypes
|
||||||
from qutebrowser.utils.completer import Completer
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
|
||||||
from qutebrowser.utils.usertypes import KeyMode
|
|
||||||
|
|
||||||
|
|
||||||
class CompletionView(QTreeView):
|
class CompletionView(QTreeView):
|
||||||
@ -94,12 +92,12 @@ class CompletionView(QTreeView):
|
|||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.completer = Completer(self)
|
self.completer = completer.Completer(self)
|
||||||
self.enabled = config.get('completion', 'show')
|
self.enabled = config.get('completion', 'show')
|
||||||
|
|
||||||
self._delegate = CompletionItemDelegate(self)
|
self._delegate = completiondelegate.CompletionItemDelegate(self)
|
||||||
self.setItemDelegate(self._delegate)
|
self.setItemDelegate(self._delegate)
|
||||||
set_register_stylesheet(self)
|
style.set_register_stylesheet(self)
|
||||||
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
|
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Minimum)
|
||||||
self.setHeaderHidden(True)
|
self.setHeaderHidden(True)
|
||||||
self.setIndentation(0)
|
self.setIndentation(0)
|
||||||
@ -169,7 +167,7 @@ class CompletionView(QTreeView):
|
|||||||
# No completion running at the moment, ignore keypress
|
# No completion running at the moment, ignore keypress
|
||||||
return
|
return
|
||||||
idx = self._next_idx(prev)
|
idx = self._next_idx(prev)
|
||||||
qt_ensure_valid(idx)
|
qtutils.qt_ensure_valid(idx)
|
||||||
self.selectionModel().setCurrentIndex(
|
self.selectionModel().setCurrentIndex(
|
||||||
idx, QItemSelectionModel.ClearAndSelect |
|
idx, QItemSelectionModel.ClearAndSelect |
|
||||||
QItemSelectionModel.Rows)
|
QItemSelectionModel.Rows)
|
||||||
@ -212,13 +210,13 @@ class CompletionView(QTreeView):
|
|||||||
selmod.clearCurrentIndex()
|
selmod.clearCurrentIndex()
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.completion', hide=True,
|
@cmdutils.register(instance='mainwindow.completion', hide=True,
|
||||||
modes=[KeyMode.command])
|
modes=[usertypes.KeyMode.command])
|
||||||
def completion_item_prev(self):
|
def completion_item_prev(self):
|
||||||
"""Select the previous completion item."""
|
"""Select the previous completion item."""
|
||||||
self._next_prev_item(prev=True)
|
self._next_prev_item(prev=True)
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.completion', hide=True,
|
@cmdutils.register(instance='mainwindow.completion', hide=True,
|
||||||
modes=[KeyMode.command])
|
modes=[usertypes.KeyMode.command])
|
||||||
def completion_item_next(self):
|
def completion_item_next(self):
|
||||||
"""Select the next completion item."""
|
"""Select the next completion item."""
|
||||||
self._next_prev_item(prev=False)
|
self._next_prev_item(prev=False)
|
||||||
|
@ -28,10 +28,9 @@ from PyQt5.QtCore import QRectF, QSize, Qt
|
|||||||
from PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption,
|
from PyQt5.QtGui import (QIcon, QPalette, QTextDocument, QTextOption,
|
||||||
QTextCursor, QAbstractTextDocumentLayout)
|
QTextCursor, QAbstractTextDocumentLayout)
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config, style
|
||||||
from qutebrowser.models.basecompletion import Role
|
from qutebrowser.models import basecompletion
|
||||||
from qutebrowser.config.style import get_stylesheet
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
|
||||||
|
|
||||||
|
|
||||||
class CompletionItemDelegate(QStyledItemDelegate):
|
class CompletionItemDelegate(QStyledItemDelegate):
|
||||||
@ -99,12 +98,12 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
|
|
||||||
text_rect_ = self._style.subElementRect(
|
text_rect_ = self._style.subElementRect(
|
||||||
self._style.SE_ItemViewItemText, self._opt, self._opt.widget)
|
self._style.SE_ItemViewItemText, self._opt, self._opt.widget)
|
||||||
qt_ensure_valid(text_rect_)
|
qtutils.qt_ensure_valid(text_rect_)
|
||||||
margin = self._style.pixelMetric(QStyle.PM_FocusFrameHMargin,
|
margin = self._style.pixelMetric(QStyle.PM_FocusFrameHMargin,
|
||||||
self._opt, self._opt.widget) + 1
|
self._opt, self._opt.widget) + 1
|
||||||
# remove width padding
|
# remove width padding
|
||||||
text_rect = text_rect_.adjusted(margin, 0, -margin, 0)
|
text_rect = text_rect_.adjusted(margin, 0, -margin, 0)
|
||||||
qt_ensure_valid(text_rect)
|
qtutils.qt_ensure_valid(text_rect)
|
||||||
# move text upwards a bit
|
# move text upwards a bit
|
||||||
if index.parent().isValid():
|
if index.parent().isValid():
|
||||||
text_rect.adjust(0, -1, 0, -1)
|
text_rect.adjust(0, -1, 0, -1)
|
||||||
@ -189,7 +188,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
self._doc.setHtml('<b>{}</b>'.format(html.escape(self._opt.text)))
|
self._doc.setHtml('<b>{}</b>'.format(html.escape(self._opt.text)))
|
||||||
self._doc.setDefaultFont(self._opt.font)
|
self._doc.setDefaultFont(self._opt.font)
|
||||||
self._doc.setDefaultTextOption(text_option)
|
self._doc.setDefaultTextOption(text_option)
|
||||||
self._doc.setDefaultStyleSheet(get_stylesheet("""
|
self._doc.setDefaultStyleSheet(style.get_stylesheet("""
|
||||||
.highlight {{
|
.highlight {{
|
||||||
{color[completion.match.fg]}
|
{color[completion.match.fg]}
|
||||||
}}
|
}}
|
||||||
@ -197,7 +196,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
self._doc.setDocumentMargin(2)
|
self._doc.setDocumentMargin(2)
|
||||||
|
|
||||||
if index.column() == 0:
|
if index.column() == 0:
|
||||||
marks = index.data(Role.marks)
|
marks = index.data(basecompletion.Role.marks)
|
||||||
if marks is None:
|
if marks is None:
|
||||||
return
|
return
|
||||||
for mark in marks:
|
for mark in marks:
|
||||||
@ -218,7 +217,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
o.rect = self._style.subElementRect(
|
o.rect = self._style.subElementRect(
|
||||||
self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget)
|
self._style.SE_ItemViewItemFocusRect, self._opt, self._opt.widget)
|
||||||
o.state |= QStyle.State_KeyboardFocusChange | QStyle.State_Item
|
o.state |= QStyle.State_KeyboardFocusChange | QStyle.State_Item
|
||||||
qt_ensure_valid(o.rect)
|
qtutils.qt_ensure_valid(o.rect)
|
||||||
if state & QStyle.State_Enabled:
|
if state & QStyle.State_Enabled:
|
||||||
cg = QPalette.Normal
|
cg = QPalette.Normal
|
||||||
else:
|
else:
|
||||||
@ -254,7 +253,7 @@ class CompletionItemDelegate(QStyledItemDelegate):
|
|||||||
docsize = self._doc.size().toSize()
|
docsize = self._doc.size().toSize()
|
||||||
size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt,
|
size = self._style.sizeFromContents(QStyle.CT_ItemViewItem, self._opt,
|
||||||
docsize, self._opt.widget)
|
docsize, self._opt.widget)
|
||||||
qt_ensure_valid(size)
|
qtutils.qt_ensure_valid(size)
|
||||||
return size + QSize(10, 3)
|
return size + QSize(10, 3)
|
||||||
|
|
||||||
def paint(self, painter, option, index):
|
def paint(self, painter, option, index):
|
||||||
|
@ -20,19 +20,18 @@
|
|||||||
"""Debugging console."""
|
"""Debugging console."""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from code import InteractiveInterpreter
|
import code
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt
|
||||||
from PyQt5.QtWidgets import QTextEdit, QWidget, QVBoxLayout, QApplication
|
from PyQt5.QtWidgets import QTextEdit, QWidget, QVBoxLayout, QApplication
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.models.cmdhistory import (History, HistoryEmptyError,
|
from qutebrowser.models import cmdhistory
|
||||||
HistoryEndReachedError)
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.misc import fake_io, disabled_excepthook
|
from qutebrowser.widgets import misc
|
||||||
from qutebrowser.widgets.misc import CommandLineEdit
|
|
||||||
|
|
||||||
|
|
||||||
class ConsoleLineEdit(CommandLineEdit):
|
class ConsoleLineEdit(misc.CommandLineEdit):
|
||||||
|
|
||||||
"""A QLineEdit which executes entered code and provides a history."""
|
"""A QLineEdit which executes entered code and provides a history."""
|
||||||
|
|
||||||
@ -56,8 +55,8 @@ class ConsoleLineEdit(CommandLineEdit):
|
|||||||
# console, not just the line edit.
|
# console, not just the line edit.
|
||||||
'self': parent,
|
'self': parent,
|
||||||
}
|
}
|
||||||
self._interpreter = InteractiveInterpreter(interpreter_locals)
|
self._interpreter = code.InteractiveInterpreter(interpreter_locals)
|
||||||
self.history = History()
|
self.history = cmdhistory.History()
|
||||||
self.returnPressed.connect(self.execute)
|
self.returnPressed.connect(self.execute)
|
||||||
self.setText('')
|
self.setText('')
|
||||||
|
|
||||||
@ -88,7 +87,7 @@ class ConsoleLineEdit(CommandLineEdit):
|
|||||||
# same.
|
# same.
|
||||||
# - We disable our exception hook, so exceptions from the console get
|
# - We disable our exception hook, so exceptions from the console get
|
||||||
# printed and don't ooen a crashdialog.
|
# printed and don't ooen a crashdialog.
|
||||||
with fake_io(self.write.emit), disabled_excepthook():
|
with utils.fake_io(self.write.emit), utils.disabled_excepthook():
|
||||||
self._more = self._interpreter.runsource(source, '<console>')
|
self._more = self._interpreter.runsource(source, '<console>')
|
||||||
self.set_prompt(self.curprompt)
|
self.set_prompt(self.curprompt)
|
||||||
if not self._more:
|
if not self._more:
|
||||||
@ -101,7 +100,8 @@ class ConsoleLineEdit(CommandLineEdit):
|
|||||||
item = self.history.start(self.text().strip())
|
item = self.history.start(self.text().strip())
|
||||||
else:
|
else:
|
||||||
item = self.history.previtem()
|
item = self.history.previtem()
|
||||||
except (HistoryEmptyError, HistoryEndReachedError):
|
except (cmdhistory.HistoryEmptyError,
|
||||||
|
cmdhistory.HistoryEndReachedError):
|
||||||
return
|
return
|
||||||
self.setText(item)
|
self.setText(item)
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ class ConsoleLineEdit(CommandLineEdit):
|
|||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
item = self.history.nextitem()
|
item = self.history.nextitem()
|
||||||
except HistoryEndReachedError:
|
except cmdhistory.HistoryEndReachedError:
|
||||||
return
|
return
|
||||||
self.setText(item)
|
self.setText(item)
|
||||||
|
|
||||||
|
@ -21,17 +21,16 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
from urllib.error import URLError
|
import urllib.error
|
||||||
from getpass import getuser
|
import getpass
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QSize
|
from PyQt5.QtCore import Qt, QSize
|
||||||
from PyQt5.QtWidgets import (QDialog, QLabel, QTextEdit, QPushButton,
|
from PyQt5.QtWidgets import (QDialog, QLabel, QTextEdit, QPushButton,
|
||||||
QVBoxLayout, QHBoxLayout)
|
QVBoxLayout, QHBoxLayout)
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
import qutebrowser.utils.misc as utils
|
from qutebrowser.utils import version, log
|
||||||
import qutebrowser.utils.log as logutils
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.utils.version import version
|
|
||||||
|
|
||||||
|
|
||||||
class _CrashDialog(QDialog):
|
class _CrashDialog(QDialog):
|
||||||
@ -124,11 +123,11 @@ class _CrashDialog(QDialog):
|
|||||||
]
|
]
|
||||||
try:
|
try:
|
||||||
self._crash_info.append(("Contact info",
|
self._crash_info.append(("Contact info",
|
||||||
"User: {}".format(getuser())))
|
"User: {}".format(getpass.getuser())))
|
||||||
except Exception as e: # pylint: disable=broad-except
|
except Exception as e: # pylint: disable=broad-except
|
||||||
self._crash_info.append(("Contact info", "User: {}: {}".format(
|
self._crash_info.append(("Contact info", "User: {}: {}".format(
|
||||||
e.__class__.__name__, e)))
|
e.__class__.__name__, e)))
|
||||||
self._crash_info.append(("Version info", version()))
|
self._crash_info.append(("Version info", version.version()))
|
||||||
try:
|
try:
|
||||||
self._crash_info.append(("Config",
|
self._crash_info.append(("Config",
|
||||||
config.instance().dump_userconfig()))
|
config.instance().dump_userconfig()))
|
||||||
@ -156,7 +155,7 @@ class _CrashDialog(QDialog):
|
|||||||
"""Paste the crash info into the pastebin."""
|
"""Paste the crash info into the pastebin."""
|
||||||
try:
|
try:
|
||||||
url = utils.pastebin(self._txt.toPlainText())
|
url = utils.pastebin(self._txt.toPlainText())
|
||||||
except (URLError, ValueError) as e:
|
except (urllib.error.URLError, ValueError) as e:
|
||||||
self._url.setText('Error while reporting: {}: {}'.format(
|
self._url.setText('Error while reporting: {}: {}'.format(
|
||||||
e.__class__.__name__, e))
|
e.__class__.__name__, e))
|
||||||
return
|
return
|
||||||
@ -228,8 +227,7 @@ class ExceptionCrashDialog(_CrashDialog):
|
|||||||
("Objects", self._objects),
|
("Objects", self._objects),
|
||||||
]
|
]
|
||||||
try:
|
try:
|
||||||
self._crash_info.append(("Debug log",
|
self._crash_info.append(("Debug log", log.ram_handler.dump_log()))
|
||||||
logutils.ram_handler.dump_log()))
|
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
self._crash_info.append(("Debug log", "{}: {}".format(
|
self._crash_info.append(("Debug log", "{}: {}".format(
|
||||||
e.__class__.__name__, e)))
|
e.__class__.__name__, e)))
|
||||||
@ -245,8 +243,8 @@ class FatalCrashDialog(_CrashDialog):
|
|||||||
_btn_pastebin: The pastebin button.
|
_btn_pastebin: The pastebin button.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, log, parent=None):
|
def __init__(self, text, parent=None):
|
||||||
self._log = log
|
self._log = text
|
||||||
self._btn_ok = None
|
self._btn_ok = None
|
||||||
self._btn_pastebin = None
|
self._btn_pastebin = None
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@ -329,8 +327,7 @@ class ReportDialog(_CrashDialog):
|
|||||||
("Objects", self._objects),
|
("Objects", self._objects),
|
||||||
]
|
]
|
||||||
try:
|
try:
|
||||||
self._crash_info.append(("Debug log",
|
self._crash_info.append(("Debug log", log.ram_handler.dump_log()))
|
||||||
logutils.ram_handler.dump_log()))
|
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
self._crash_info.append(("Debug log", "{}: {}".format(
|
self._crash_info.append(("Debug log", "{}: {}".format(
|
||||||
e.__class__.__name__, e)))
|
e.__class__.__name__, e)))
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
from PyQt5.QtCore import pyqtSlot, QSize, Qt
|
from PyQt5.QtCore import pyqtSlot, QSize, Qt
|
||||||
from PyQt5.QtWidgets import QListView, QSizePolicy, QMenu
|
from PyQt5.QtWidgets import QListView, QSizePolicy, QMenu
|
||||||
|
|
||||||
from qutebrowser.models.downloadmodel import DownloadModel, Role
|
from qutebrowser.models import downloadmodel
|
||||||
from qutebrowser.config.style import set_register_stylesheet
|
from qutebrowser.config import style
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
from qutebrowser.utils import qt as qtutils
|
||||||
|
|
||||||
|
|
||||||
class DownloadView(QListView):
|
class DownloadView(QListView):
|
||||||
@ -49,13 +49,13 @@ class DownloadView(QListView):
|
|||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
set_register_stylesheet(self)
|
style.set_register_stylesheet(self)
|
||||||
self.setResizeMode(QListView.Adjust)
|
self.setResizeMode(QListView.Adjust)
|
||||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
|
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
|
||||||
self.setFlow(QListView.LeftToRight)
|
self.setFlow(QListView.LeftToRight)
|
||||||
self._menu = None
|
self._menu = None
|
||||||
self._model = DownloadModel(self)
|
self._model = downloadmodel.DownloadModel(self)
|
||||||
self._model.rowsInserted.connect(self.updateGeometry)
|
self._model.rowsInserted.connect(self.updateGeometry)
|
||||||
self._model.rowsRemoved.connect(self.updateGeometry)
|
self._model.rowsRemoved.connect(self.updateGeometry)
|
||||||
self.setModel(self._model)
|
self.setModel(self._model)
|
||||||
@ -73,7 +73,7 @@ class DownloadView(QListView):
|
|||||||
index = self.indexAt(point)
|
index = self.indexAt(point)
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
return
|
return
|
||||||
item = self.model().data(index, Role.item)
|
item = self.model().data(index, downloadmodel.Role.item)
|
||||||
self._menu = QMenu(self)
|
self._menu = QMenu(self)
|
||||||
cancel = self._menu.addAction("Cancel")
|
cancel = self._menu.addAction("Cancel")
|
||||||
cancel.triggered.connect(item.cancel)
|
cancel.triggered.connect(item.cancel)
|
||||||
@ -91,5 +91,5 @@ class DownloadView(QListView):
|
|||||||
size = QSize(0, height + 2)
|
size = QSize(0, height + 2)
|
||||||
else:
|
else:
|
||||||
size = QSize(0, 0)
|
size = QSize(0, 0)
|
||||||
qt_ensure_valid(size)
|
qtutils.qt_ensure_valid(size)
|
||||||
return size
|
return size
|
||||||
|
@ -20,21 +20,17 @@
|
|||||||
"""The main window of qutebrowser."""
|
"""The main window of qutebrowser."""
|
||||||
|
|
||||||
import binascii
|
import binascii
|
||||||
from base64 import b64decode
|
import base64
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot, QRect, QPoint, QCoreApplication, QTimer
|
from PyQt5.QtCore import pyqtSlot, QRect, QPoint, QCoreApplication, QTimer
|
||||||
from PyQt5.QtWidgets import QWidget, QVBoxLayout
|
from PyQt5.QtWidgets import QWidget, QVBoxLayout
|
||||||
|
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import utils as cmdutils
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.utils import message, log, usertypes
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.widgets.statusbar.bar import StatusBar
|
from qutebrowser.widgets import tabbedbrowser, completion, downloads
|
||||||
from qutebrowser.widgets.tabbedbrowser import TabbedBrowser
|
from qutebrowser.widgets.statusbar import bar
|
||||||
from qutebrowser.widgets.completion import CompletionView
|
|
||||||
from qutebrowser.widgets.downloads import DownloadView
|
|
||||||
from qutebrowser.utils.usertypes import PromptMode
|
|
||||||
from qutebrowser.utils.qt import check_overflow
|
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QWidget):
|
class MainWindow(QWidget):
|
||||||
@ -57,9 +53,9 @@ class MainWindow(QWidget):
|
|||||||
self.setWindowTitle('qutebrowser')
|
self.setWindowTitle('qutebrowser')
|
||||||
try:
|
try:
|
||||||
stateconf = QCoreApplication.instance().stateconfig
|
stateconf = QCoreApplication.instance().stateconfig
|
||||||
base64 = stateconf['geometry']['mainwindow']
|
data = stateconf['geometry']['mainwindow']
|
||||||
log.init.debug("Restoring mainwindow from {}".format(base64))
|
log.init.debug("Restoring mainwindow from {}".format(data))
|
||||||
geom = b64decode(base64, validate=True)
|
geom = base64.b64decode(data, validate=True)
|
||||||
except (KeyError, binascii.Error) as e:
|
except (KeyError, binascii.Error) as e:
|
||||||
log.init.warning("Error while reading geometry: {}: {}".format(
|
log.init.warning("Error while reading geometry: {}: {}".format(
|
||||||
e.__class__.__name__, e))
|
e.__class__.__name__, e))
|
||||||
@ -81,17 +77,17 @@ class MainWindow(QWidget):
|
|||||||
self._vbox.setContentsMargins(0, 0, 0, 0)
|
self._vbox.setContentsMargins(0, 0, 0, 0)
|
||||||
self._vbox.setSpacing(0)
|
self._vbox.setSpacing(0)
|
||||||
|
|
||||||
self.downloadview = DownloadView()
|
self.downloadview = downloads.DownloadView()
|
||||||
self._vbox.addWidget(self.downloadview)
|
self._vbox.addWidget(self.downloadview)
|
||||||
self.downloadview.show()
|
self.downloadview.show()
|
||||||
|
|
||||||
self.tabs = TabbedBrowser()
|
self.tabs = tabbedbrowser.TabbedBrowser()
|
||||||
self.tabs.title_changed.connect(self.setWindowTitle)
|
self.tabs.title_changed.connect(self.setWindowTitle)
|
||||||
self._vbox.addWidget(self.tabs)
|
self._vbox.addWidget(self.tabs)
|
||||||
|
|
||||||
self.completion = CompletionView(self)
|
self.completion = completion.CompletionView(self)
|
||||||
|
|
||||||
self.status = StatusBar()
|
self.status = bar.StatusBar()
|
||||||
self._vbox.addWidget(self.status)
|
self._vbox.addWidget(self.status)
|
||||||
|
|
||||||
# When we're here the statusbar might not even really exist yet, so
|
# When we're here the statusbar might not even really exist yet, so
|
||||||
@ -139,7 +135,7 @@ class MainWindow(QWidget):
|
|||||||
# hpoint now would be the bottom-left edge of the widget if it was on
|
# hpoint now would be the bottom-left edge of the widget if it was on
|
||||||
# the top of the main window.
|
# the top of the main window.
|
||||||
topleft_y = self.height() - self.status.height() - height
|
topleft_y = self.height() - self.status.height() - height
|
||||||
topleft_y = check_overflow(topleft_y, 'int', fatal=False)
|
topleft_y = qtutils.check_overflow(topleft_y, 'int', fatal=False)
|
||||||
topleft = QPoint(0, topleft_y)
|
topleft = QPoint(0, topleft_y)
|
||||||
bottomright = self.status.geometry().topRight()
|
bottomright = self.status.geometry().topRight()
|
||||||
rect = QRect(topleft, bottomright)
|
rect = QRect(topleft, bottomright)
|
||||||
@ -178,7 +174,8 @@ class MainWindow(QWidget):
|
|||||||
else:
|
else:
|
||||||
text = "Close {} {}?".format(
|
text = "Close {} {}?".format(
|
||||||
count, "tab" if count == 1 else "tabs")
|
count, "tab" if count == 1 else "tabs")
|
||||||
confirmed = message.ask(text, PromptMode.yesno, default=True)
|
confirmed = message.ask(text, usertypes.PromptMode.yesno,
|
||||||
|
default=True)
|
||||||
if confirmed:
|
if confirmed:
|
||||||
e.accept()
|
e.accept()
|
||||||
else:
|
else:
|
||||||
|
@ -23,7 +23,7 @@ from PyQt5.QtCore import pyqtSlot
|
|||||||
from PyQt5.QtWidgets import QLineEdit
|
from PyQt5.QtWidgets import QLineEdit
|
||||||
from PyQt5.QtGui import QValidator
|
from PyQt5.QtGui import QValidator
|
||||||
|
|
||||||
from qutebrowser.models.cmdhistory import History
|
from qutebrowser.models import cmdhistory
|
||||||
|
|
||||||
|
|
||||||
class MinimalLineEditMixin:
|
class MinimalLineEditMixin:
|
||||||
@ -55,7 +55,7 @@ class CommandLineEdit(QLineEdit):
|
|||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.history = History()
|
self.history = cmdhistory.History()
|
||||||
self._validator = _CommandValidator(self)
|
self._validator = _CommandValidator(self)
|
||||||
self.setValidator(self._validator)
|
self.setValidator(self._validator)
|
||||||
self.textEdited.connect(self.on_text_edited)
|
self.textEdited.connect(self.on_text_edited)
|
||||||
|
@ -19,27 +19,22 @@
|
|||||||
|
|
||||||
"""The main statusbar widget."""
|
"""The main statusbar widget."""
|
||||||
|
|
||||||
from collections import deque
|
import collections
|
||||||
from datetime import datetime
|
import datetime
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty, Qt
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, pyqtProperty, Qt
|
||||||
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QStackedLayout, QSizePolicy
|
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QStackedLayout, QSizePolicy
|
||||||
|
|
||||||
import qutebrowser.keyinput.modeman as modeman
|
from qutebrowser.keyinput import modeman
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config, style
|
||||||
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.log import statusbar as logger
|
from qutebrowser.utils.log import statusbar as logger
|
||||||
from qutebrowser.widgets.statusbar.command import Command
|
from qutebrowser.widgets.statusbar import (command, progress, keystring,
|
||||||
from qutebrowser.widgets.statusbar.progress import Progress
|
percentage, url, prompt)
|
||||||
from qutebrowser.widgets.statusbar.text import Text
|
from qutebrowser.widgets.statusbar import text as textwidget
|
||||||
from qutebrowser.widgets.statusbar.keystring import KeyString
|
|
||||||
from qutebrowser.widgets.statusbar.percentage import Percentage
|
|
||||||
from qutebrowser.widgets.statusbar.url import UrlText
|
|
||||||
from qutebrowser.widgets.statusbar.prompt import Prompt
|
|
||||||
from qutebrowser.config.style import set_register_stylesheet, get_stylesheet
|
|
||||||
from qutebrowser.utils.usertypes import Timer, KeyMode, enum
|
|
||||||
|
|
||||||
|
|
||||||
PreviousWidget = enum('PreviousWidget', 'none', 'prompt', 'command')
|
PreviousWidget = usertypes.enum('PreviousWidget', 'none', 'prompt', 'command')
|
||||||
|
|
||||||
|
|
||||||
class StatusBar(QWidget):
|
class StatusBar(QWidget):
|
||||||
@ -128,7 +123,7 @@ class StatusBar(QWidget):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setObjectName(self.__class__.__name__)
|
self.setObjectName(self.__class__.__name__)
|
||||||
self.setAttribute(Qt.WA_StyledBackground)
|
self.setAttribute(Qt.WA_StyledBackground)
|
||||||
set_register_stylesheet(self)
|
style.set_register_stylesheet(self)
|
||||||
|
|
||||||
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
|
self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
|
||||||
|
|
||||||
@ -143,18 +138,18 @@ class StatusBar(QWidget):
|
|||||||
self._hbox.addLayout(self._stack)
|
self._hbox.addLayout(self._stack)
|
||||||
self._stack.setContentsMargins(0, 0, 0, 0)
|
self._stack.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
self.cmd = Command()
|
self.cmd = command.Command()
|
||||||
self._stack.addWidget(self.cmd)
|
self._stack.addWidget(self.cmd)
|
||||||
|
|
||||||
self.txt = Text()
|
self.txt = textwidget.Text()
|
||||||
self._stack.addWidget(self.txt)
|
self._stack.addWidget(self.txt)
|
||||||
self._timer_was_active = False
|
self._timer_was_active = False
|
||||||
self._text_queue = deque()
|
self._text_queue = collections.deque()
|
||||||
self._text_pop_timer = Timer(self, 'statusbar_text_pop')
|
self._text_pop_timer = usertypes.Timer(self, 'statusbar_text_pop')
|
||||||
self._text_pop_timer.setInterval(config.get('ui', 'message-timeout'))
|
self._text_pop_timer.setInterval(config.get('ui', 'message-timeout'))
|
||||||
self._text_pop_timer.timeout.connect(self._pop_text)
|
self._text_pop_timer.timeout.connect(self._pop_text)
|
||||||
|
|
||||||
self.prompt = Prompt()
|
self.prompt = prompt.Prompt()
|
||||||
self._stack.addWidget(self.prompt)
|
self._stack.addWidget(self.prompt)
|
||||||
self._previous_widget = PreviousWidget.none
|
self._previous_widget = PreviousWidget.none
|
||||||
|
|
||||||
@ -165,19 +160,19 @@ class StatusBar(QWidget):
|
|||||||
self.prompt.hide_prompt.connect(self._hide_prompt_widget)
|
self.prompt.hide_prompt.connect(self._hide_prompt_widget)
|
||||||
self._hide_prompt_widget()
|
self._hide_prompt_widget()
|
||||||
|
|
||||||
self.keystring = KeyString()
|
self.keystring = keystring.KeyString()
|
||||||
self._hbox.addWidget(self.keystring)
|
self._hbox.addWidget(self.keystring)
|
||||||
|
|
||||||
self.url = UrlText()
|
self.url = url.UrlText()
|
||||||
self._hbox.addWidget(self.url)
|
self._hbox.addWidget(self.url)
|
||||||
|
|
||||||
self.percentage = Percentage()
|
self.percentage = percentage.Percentage()
|
||||||
self._hbox.addWidget(self.percentage)
|
self._hbox.addWidget(self.percentage)
|
||||||
|
|
||||||
# We add a parent to Progress here because it calls self.show() based
|
# We add a parent to Progress here because it calls self.show() based
|
||||||
# on some signals, and if that happens before it's added to the layout,
|
# on some signals, and if that happens before it's added to the layout,
|
||||||
# it will quickly blink up as independent window.
|
# it will quickly blink up as independent window.
|
||||||
self.prog = Progress(self)
|
self.prog = progress.Progress(self)
|
||||||
self._hbox.addWidget(self.prog)
|
self._hbox.addWidget(self.prog)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@ -198,7 +193,7 @@ class StatusBar(QWidget):
|
|||||||
"""
|
"""
|
||||||
logger.debug("Setting error to {}".format(val))
|
logger.debug("Setting error to {}".format(val))
|
||||||
self._error = val
|
self._error = val
|
||||||
self.setStyleSheet(get_stylesheet(self.STYLESHEET))
|
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
|
||||||
if val:
|
if val:
|
||||||
# If we got an error while command/prompt was shown, raise the text
|
# If we got an error while command/prompt was shown, raise the text
|
||||||
# widget.
|
# widget.
|
||||||
@ -219,7 +214,7 @@ class StatusBar(QWidget):
|
|||||||
"""
|
"""
|
||||||
logger.debug("Setting prompt_active to {}".format(val))
|
logger.debug("Setting prompt_active to {}".format(val))
|
||||||
self._prompt_active = val
|
self._prompt_active = val
|
||||||
self.setStyleSheet(get_stylesheet(self.STYLESHEET))
|
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
|
||||||
|
|
||||||
@pyqtProperty(bool)
|
@pyqtProperty(bool)
|
||||||
def insert_active(self):
|
def insert_active(self):
|
||||||
@ -236,7 +231,7 @@ class StatusBar(QWidget):
|
|||||||
"""
|
"""
|
||||||
logger.debug("Setting insert_active to {}".format(val))
|
logger.debug("Setting insert_active to {}".format(val))
|
||||||
self._insert_active = val
|
self._insert_active = val
|
||||||
self.setStyleSheet(get_stylesheet(self.STYLESHEET))
|
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
|
||||||
|
|
||||||
def _pop_text(self):
|
def _pop_text(self):
|
||||||
"""Display a text in the statusbar and pop it from _text_queue."""
|
"""Display a text in the statusbar and pop it from _text_queue."""
|
||||||
@ -316,7 +311,7 @@ class StatusBar(QWidget):
|
|||||||
"""
|
"""
|
||||||
# FIXME probably using a QTime here would be easier.
|
# FIXME probably using a QTime here would be easier.
|
||||||
logger.debug("Displaying text: {} (error={})".format(text, error))
|
logger.debug("Displaying text: {} (error={})".format(text, error))
|
||||||
now = datetime.now()
|
now = datetime.datetime.now()
|
||||||
mindelta = config.get('ui', 'message-timeout')
|
mindelta = config.get('ui', 'message-timeout')
|
||||||
delta = (None if self._last_text_time is None
|
delta = (None if self._last_text_time is None
|
||||||
else now - self._last_text_time)
|
else now - self._last_text_time)
|
||||||
@ -379,20 +374,20 @@ class StatusBar(QWidget):
|
|||||||
"""Set a normal (persistent) text in the status bar."""
|
"""Set a normal (persistent) text in the status bar."""
|
||||||
self.txt.normaltext = val
|
self.txt.normaltext = val
|
||||||
|
|
||||||
@pyqtSlot(KeyMode)
|
@pyqtSlot(usertypes.KeyMode)
|
||||||
def on_mode_entered(self, mode):
|
def on_mode_entered(self, mode):
|
||||||
"""Mark certain modes in the commandline."""
|
"""Mark certain modes in the commandline."""
|
||||||
if mode in modeman.instance().passthrough:
|
if mode in modeman.instance().passthrough:
|
||||||
self.txt.normaltext = "-- {} MODE --".format(mode.name.upper())
|
self.txt.normaltext = "-- {} MODE --".format(mode.name.upper())
|
||||||
if mode == KeyMode.insert:
|
if mode == usertypes.KeyMode.insert:
|
||||||
self.insert_active = True
|
self.insert_active = True
|
||||||
|
|
||||||
@pyqtSlot(KeyMode)
|
@pyqtSlot(usertypes.KeyMode)
|
||||||
def on_mode_left(self, mode):
|
def on_mode_left(self, mode):
|
||||||
"""Clear marked mode."""
|
"""Clear marked mode."""
|
||||||
if mode in modeman.instance().passthrough:
|
if mode in modeman.instance().passthrough:
|
||||||
self.txt.normaltext = ""
|
self.txt.normaltext = ""
|
||||||
if mode == KeyMode.insert:
|
if mode == usertypes.KeyMode.insert:
|
||||||
self.insert_active = False
|
self.insert_active = False
|
||||||
|
|
||||||
@pyqtSlot(str, str)
|
@pyqtSlot(str, str)
|
||||||
|
@ -22,19 +22,17 @@
|
|||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtWidgets import QSizePolicy, QApplication
|
from PyQt5.QtWidgets import QSizePolicy, QApplication
|
||||||
|
|
||||||
import qutebrowser.keyinput.modeman as modeman
|
from qutebrowser.keyinput import modeman, modeparsers
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import runners
|
||||||
from qutebrowser.widgets.misc import MinimalLineEditMixin, CommandLineEdit
|
from qutebrowser.commands import utils as cmdutils
|
||||||
from qutebrowser.commands.runners import CommandRunner
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
from qutebrowser.keyinput.modeparsers import STARTCHARS
|
from qutebrowser.widgets import misc
|
||||||
|
from qutebrowser.models import cmdhistory
|
||||||
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.log import completion as logger
|
from qutebrowser.utils.log import completion as logger
|
||||||
from qutebrowser.models.cmdhistory import (HistoryEmptyError,
|
|
||||||
HistoryEndReachedError)
|
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
|
||||||
from qutebrowser.utils.usertypes import KeyMode
|
|
||||||
|
|
||||||
|
|
||||||
class Command(MinimalLineEditMixin, CommandLineEdit):
|
class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
||||||
|
|
||||||
"""The commandline part of the statusbar.
|
"""The commandline part of the statusbar.
|
||||||
|
|
||||||
@ -76,8 +74,8 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
|
|||||||
# for a possible fix.
|
# for a possible fix.
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
CommandLineEdit.__init__(self, parent)
|
misc.CommandLineEdit.__init__(self, parent)
|
||||||
MinimalLineEditMixin.__init__(self)
|
misc.MinimalLineEditMixin.__init__(self)
|
||||||
self.cursor_part = 0
|
self.cursor_part = 0
|
||||||
self.history.history = QApplication.instance().cmd_history.data
|
self.history.history = QApplication.instance().cmd_history.data
|
||||||
self._empty_item_idx = None
|
self._empty_item_idx = None
|
||||||
@ -92,7 +90,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
|
|||||||
text = self.text()
|
text = self.text()
|
||||||
if not text:
|
if not text:
|
||||||
return ''
|
return ''
|
||||||
elif text[0] in STARTCHARS:
|
elif text[0] in modeparsers.STARTCHARS:
|
||||||
return text[0]
|
return text[0]
|
||||||
else:
|
else:
|
||||||
return ''
|
return ''
|
||||||
@ -109,7 +107,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
|
|||||||
# Text is only whitespace so we treat this as a single element with
|
# Text is only whitespace so we treat this as a single element with
|
||||||
# the whitespace.
|
# the whitespace.
|
||||||
return [text]
|
return [text]
|
||||||
runner = CommandRunner()
|
runner = runners.CommandRunner()
|
||||||
parts = runner.parse(text, fallback=True, alias_no_args=False)
|
parts = runner.parse(text, fallback=True, alias_no_args=False)
|
||||||
if self._empty_item_idx is not None:
|
if self._empty_item_idx is not None:
|
||||||
logger.debug("Empty element queued at {}, inserting.".format(
|
logger.debug("Empty element queued at {}, inserting.".format(
|
||||||
@ -179,8 +177,9 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
|
|||||||
strings: A list of strings to set.
|
strings: A list of strings to set.
|
||||||
"""
|
"""
|
||||||
text = ' '.join(strings)
|
text = ' '.join(strings)
|
||||||
if not text[0] in STARTCHARS:
|
if not text[0] in modeparsers.STARTCHARS:
|
||||||
raise CommandError("Invalid command text '{}'.".format(text))
|
raise cmdexc.CommandError(
|
||||||
|
"Invalid command text '{}'.".format(text))
|
||||||
self.set_cmd_text(text)
|
self.set_cmd_text(text)
|
||||||
|
|
||||||
@pyqtSlot(str, bool)
|
@pyqtSlot(str, bool)
|
||||||
@ -215,7 +214,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
|
|||||||
self.show_cmd.emit()
|
self.show_cmd.emit()
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.status.cmd', hide=True,
|
@cmdutils.register(instance='mainwindow.status.cmd', hide=True,
|
||||||
modes=[KeyMode.command])
|
modes=[usertypes.KeyMode.command])
|
||||||
def command_history_prev(self):
|
def command_history_prev(self):
|
||||||
"""Go back in the commandline history."""
|
"""Go back in the commandline history."""
|
||||||
try:
|
try:
|
||||||
@ -223,26 +222,27 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
|
|||||||
item = self.history.start(self.text().strip())
|
item = self.history.start(self.text().strip())
|
||||||
else:
|
else:
|
||||||
item = self.history.previtem()
|
item = self.history.previtem()
|
||||||
except (HistoryEmptyError, HistoryEndReachedError):
|
except (cmdhistory.HistoryEmptyError,
|
||||||
|
cmdhistory.HistoryEndReachedError):
|
||||||
return
|
return
|
||||||
if item:
|
if item:
|
||||||
self.set_cmd_text(item)
|
self.set_cmd_text(item)
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.status.cmd', hide=True,
|
@cmdutils.register(instance='mainwindow.status.cmd', hide=True,
|
||||||
modes=[KeyMode.command])
|
modes=[usertypes.KeyMode.command])
|
||||||
def command_history_next(self):
|
def command_history_next(self):
|
||||||
"""Go forward in the commandline history."""
|
"""Go forward in the commandline history."""
|
||||||
if not self.history.browsing:
|
if not self.history.browsing:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
item = self.history.nextitem()
|
item = self.history.nextitem()
|
||||||
except HistoryEndReachedError:
|
except cmdhistory.HistoryEndReachedError:
|
||||||
return
|
return
|
||||||
if item:
|
if item:
|
||||||
self.set_cmd_text(item)
|
self.set_cmd_text(item)
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.status.cmd', hide=True,
|
@cmdutils.register(instance='mainwindow.status.cmd', hide=True,
|
||||||
modes=[KeyMode.command])
|
modes=[usertypes.KeyMode.command])
|
||||||
def command_accept(self):
|
def command_accept(self):
|
||||||
"""Execute the command currently in the commandline.
|
"""Execute the command currently in the commandline.
|
||||||
|
|
||||||
@ -258,7 +258,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
|
|||||||
}
|
}
|
||||||
text = self.text()
|
text = self.text()
|
||||||
self.history.append(text)
|
self.history.append(text)
|
||||||
modeman.leave(KeyMode.command, 'cmd accept')
|
modeman.leave(usertypes.KeyMode.command, 'cmd accept')
|
||||||
if text[0] in signals:
|
if text[0] in signals:
|
||||||
signals[text[0]].emit(text.lstrip(text[0]))
|
signals[text[0]].emit(text.lstrip(text[0]))
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
|
|||||||
# here, but that's already done for us by cursorPositionChanged
|
# here, but that's already done for us by cursorPositionChanged
|
||||||
# anyways, so we don't need to do it twice.
|
# anyways, so we don't need to do it twice.
|
||||||
|
|
||||||
@pyqtSlot(KeyMode)
|
@pyqtSlot(usertypes.KeyMode)
|
||||||
def on_mode_left(self, mode):
|
def on_mode_left(self, mode):
|
||||||
"""Clear up when ommand mode was left.
|
"""Clear up when ommand mode was left.
|
||||||
|
|
||||||
@ -286,7 +286,7 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
|
|||||||
clear_completion_selection: Always emitted.
|
clear_completion_selection: Always emitted.
|
||||||
hide_completion: Always emitted so the completion is hidden.
|
hide_completion: Always emitted so the completion is hidden.
|
||||||
"""
|
"""
|
||||||
if mode == KeyMode.command:
|
if mode == usertypes.KeyMode.command:
|
||||||
self.setText('')
|
self.setText('')
|
||||||
self.history.stop()
|
self.history.stop()
|
||||||
self.hide_cmd.emit()
|
self.hide_cmd.emit()
|
||||||
@ -295,14 +295,14 @@ class Command(MinimalLineEditMixin, CommandLineEdit):
|
|||||||
|
|
||||||
def focusInEvent(self, e):
|
def focusInEvent(self, e):
|
||||||
"""Extend focusInEvent to enter command mode."""
|
"""Extend focusInEvent to enter command mode."""
|
||||||
modeman.maybe_enter(KeyMode.command, 'cmd focus')
|
modeman.maybe_enter(usertypes.KeyMode.command, 'cmd focus')
|
||||||
super().focusInEvent(e)
|
super().focusInEvent(e)
|
||||||
|
|
||||||
def setText(self, text):
|
def setText(self, text):
|
||||||
"""Extend setText to set prefix and make sure the prompt is ok."""
|
"""Extend setText to set prefix and make sure the prompt is ok."""
|
||||||
if not text:
|
if not text:
|
||||||
pass
|
pass
|
||||||
elif text[0] in STARTCHARS:
|
elif text[0] in modeparsers.STARTCHARS:
|
||||||
super().set_prompt(text[0])
|
super().set_prompt(text[0])
|
||||||
else:
|
else:
|
||||||
raise AssertionError("setText got called with invalid text "
|
raise AssertionError("setText got called with invalid text "
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
"""Keychain string displayed in the statusbar."""
|
"""Keychain string displayed in the statusbar."""
|
||||||
|
|
||||||
from qutebrowser.widgets.statusbar.textbase import TextBase
|
from qutebrowser.widgets.statusbar import textbase
|
||||||
|
|
||||||
|
|
||||||
class KeyString(TextBase):
|
class KeyString(textbase.TextBase):
|
||||||
|
|
||||||
"""Keychain string displayed in the statusbar."""
|
"""Keychain string displayed in the statusbar."""
|
||||||
|
|
||||||
|
@ -21,10 +21,10 @@
|
|||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot
|
from PyQt5.QtCore import pyqtSlot
|
||||||
|
|
||||||
from qutebrowser.widgets.statusbar.textbase import TextBase
|
from qutebrowser.widgets.statusbar import textbase
|
||||||
|
|
||||||
|
|
||||||
class Percentage(TextBase):
|
class Percentage(textbase.TextBase):
|
||||||
|
|
||||||
"""Reading percentage displayed in the statusbar."""
|
"""Reading percentage displayed in the statusbar."""
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
from PyQt5.QtCore import pyqtSlot
|
from PyQt5.QtCore import pyqtSlot
|
||||||
from PyQt5.QtWidgets import QProgressBar, QSizePolicy
|
from PyQt5.QtWidgets import QProgressBar, QSizePolicy
|
||||||
|
|
||||||
from qutebrowser.widgets.webview import LoadStatus
|
from qutebrowser.widgets import webview
|
||||||
from qutebrowser.config.style import set_register_stylesheet
|
from qutebrowser.config import style
|
||||||
|
|
||||||
|
|
||||||
class Progress(QProgressBar):
|
class Progress(QProgressBar):
|
||||||
@ -50,7 +50,7 @@ class Progress(QProgressBar):
|
|||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
set_register_stylesheet(self)
|
style.set_register_stylesheet(self)
|
||||||
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Ignored)
|
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Ignored)
|
||||||
self.setTextVisible(False)
|
self.setTextVisible(False)
|
||||||
self.hide()
|
self.hide()
|
||||||
@ -72,7 +72,7 @@ class Progress(QProgressBar):
|
|||||||
# sometimes.
|
# sometimes.
|
||||||
return
|
return
|
||||||
self.setValue(tab.progress)
|
self.setValue(tab.progress)
|
||||||
if tab.load_status == LoadStatus.loading:
|
if tab.load_status == webview.LoadStatus.loading:
|
||||||
self.show()
|
self.show()
|
||||||
else:
|
else:
|
||||||
self.hide()
|
self.hide()
|
||||||
|
@ -22,18 +22,17 @@
|
|||||||
from PyQt5.QtCore import pyqtSignal
|
from PyQt5.QtCore import pyqtSignal
|
||||||
from PyQt5.QtWidgets import QHBoxLayout, QWidget, QLineEdit
|
from PyQt5.QtWidgets import QHBoxLayout, QWidget, QLineEdit
|
||||||
|
|
||||||
from qutebrowser.widgets.misc import MinimalLineEditMixin
|
from qutebrowser.widgets import misc
|
||||||
from qutebrowser.widgets.statusbar.textbase import TextBase
|
from qutebrowser.widgets.statusbar import textbase, prompter
|
||||||
from qutebrowser.widgets.statusbar.prompter import Prompter
|
|
||||||
|
|
||||||
|
|
||||||
class PromptLineEdit(MinimalLineEditMixin, QLineEdit):
|
class PromptLineEdit(misc.MinimalLineEditMixin, QLineEdit):
|
||||||
|
|
||||||
"""QLineEdit with a minimal stylesheet."""
|
"""QLineEdit with a minimal stylesheet."""
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QLineEdit.__init__(self, parent)
|
QLineEdit.__init__(self, parent)
|
||||||
MinimalLineEditMixin.__init__(self)
|
misc.MinimalLineEditMixin.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
class Prompt(QWidget):
|
class Prompt(QWidget):
|
||||||
@ -60,13 +59,13 @@ class Prompt(QWidget):
|
|||||||
self._hbox.setContentsMargins(0, 0, 0, 0)
|
self._hbox.setContentsMargins(0, 0, 0, 0)
|
||||||
self._hbox.setSpacing(5)
|
self._hbox.setSpacing(5)
|
||||||
|
|
||||||
self.txt = TextBase()
|
self.txt = textbase.TextBase()
|
||||||
self._hbox.addWidget(self.txt)
|
self._hbox.addWidget(self.txt)
|
||||||
|
|
||||||
self.lineedit = PromptLineEdit()
|
self.lineedit = PromptLineEdit()
|
||||||
self._hbox.addWidget(self.lineedit)
|
self._hbox.addWidget(self.lineedit)
|
||||||
|
|
||||||
self.prompter = Prompter(self)
|
self.prompter = prompter.Prompter(self)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<{}>'.format(self.__class__.__name__)
|
return '<{}>'.format(self.__class__.__name__)
|
||||||
|
@ -19,20 +19,21 @@
|
|||||||
|
|
||||||
"""Manager for questions to be shown in the statusbar."""
|
"""Manager for questions to be shown in the statusbar."""
|
||||||
|
|
||||||
from collections import namedtuple, deque
|
import collections
|
||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot, QTimer
|
from PyQt5.QtCore import pyqtSlot, QTimer
|
||||||
from PyQt5.QtWidgets import QLineEdit
|
from PyQt5.QtWidgets import QLineEdit
|
||||||
|
|
||||||
import qutebrowser.keyinput.modeman as modeman
|
from qutebrowser.keyinput import modeman
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import utils as cmdutils
|
||||||
from qutebrowser.utils.usertypes import PromptMode, Question, KeyMode
|
from qutebrowser.utils import usertypes
|
||||||
from qutebrowser.utils.qt import EventLoop
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.log import statusbar as logger
|
from qutebrowser.utils.log import statusbar as logger
|
||||||
|
|
||||||
|
|
||||||
PromptContext = namedtuple('PromptContext', ['question', 'text', 'input_text',
|
PromptContext = collections.namedtuple('PromptContext',
|
||||||
'echo_mode', 'input_visible'])
|
['question', 'text', 'input_text',
|
||||||
|
'echo_mode', 'input_visible'])
|
||||||
|
|
||||||
|
|
||||||
class Prompter:
|
class Prompter:
|
||||||
@ -67,7 +68,7 @@ class Prompter:
|
|||||||
def __init__(self, prompt):
|
def __init__(self, prompt):
|
||||||
self.question = None
|
self.question = None
|
||||||
self._loops = []
|
self._loops = []
|
||||||
self._queue = deque()
|
self._queue = collections.deque()
|
||||||
self._busy = False
|
self._busy = False
|
||||||
self._prompt = prompt
|
self._prompt = prompt
|
||||||
|
|
||||||
@ -124,7 +125,7 @@ class Prompter:
|
|||||||
Raise:
|
Raise:
|
||||||
ValueError if the set PromptMode is invalid.
|
ValueError if the set PromptMode is invalid.
|
||||||
"""
|
"""
|
||||||
if self.question.mode == PromptMode.yesno:
|
if self.question.mode == usertypes.PromptMode.yesno:
|
||||||
if self.question.default is None:
|
if self.question.default is None:
|
||||||
suffix = ""
|
suffix = ""
|
||||||
elif self.question.default:
|
elif self.question.default:
|
||||||
@ -133,23 +134,23 @@ class Prompter:
|
|||||||
suffix = " (no)"
|
suffix = " (no)"
|
||||||
self._prompt.txt.setText(self.question.text + suffix)
|
self._prompt.txt.setText(self.question.text + suffix)
|
||||||
self._prompt.lineedit.hide()
|
self._prompt.lineedit.hide()
|
||||||
mode = KeyMode.yesno
|
mode = usertypes.KeyMode.yesno
|
||||||
elif self.question.mode == PromptMode.text:
|
elif self.question.mode == usertypes.PromptMode.text:
|
||||||
self._prompt.txt.setText(self.question.text)
|
self._prompt.txt.setText(self.question.text)
|
||||||
if self.question.default:
|
if self.question.default:
|
||||||
self._prompt.lineedit.setText(self.question.default)
|
self._prompt.lineedit.setText(self.question.default)
|
||||||
self._prompt.lineedit.show()
|
self._prompt.lineedit.show()
|
||||||
mode = KeyMode.prompt
|
mode = usertypes.KeyMode.prompt
|
||||||
elif self.question.mode == PromptMode.user_pwd:
|
elif self.question.mode == usertypes.PromptMode.user_pwd:
|
||||||
self._prompt.txt.setText(self.question.text)
|
self._prompt.txt.setText(self.question.text)
|
||||||
if self.question.default:
|
if self.question.default:
|
||||||
self._prompt.lineedit.setText(self.question.default)
|
self._prompt.lineedit.setText(self.question.default)
|
||||||
self._prompt.lineedit.show()
|
self._prompt.lineedit.show()
|
||||||
mode = KeyMode.prompt
|
mode = usertypes.KeyMode.prompt
|
||||||
elif self.question.mode == PromptMode.alert:
|
elif self.question.mode == usertypes.PromptMode.alert:
|
||||||
self._prompt.txt.setText(self.question.text + ' (ok)')
|
self._prompt.txt.setText(self.question.text + ' (ok)')
|
||||||
self._prompt.lineedit.hide()
|
self._prompt.lineedit.hide()
|
||||||
mode = KeyMode.prompt
|
mode = usertypes.KeyMode.prompt
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid prompt mode!")
|
raise ValueError("Invalid prompt mode!")
|
||||||
self._prompt.lineedit.setFocus()
|
self._prompt.lineedit.setFocus()
|
||||||
@ -174,10 +175,10 @@ class Prompter:
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@pyqtSlot(KeyMode)
|
@pyqtSlot(usertypes.KeyMode)
|
||||||
def on_mode_left(self, mode):
|
def on_mode_left(self, mode):
|
||||||
"""Clear and reset input when the mode was left."""
|
"""Clear and reset input when the mode was left."""
|
||||||
if mode in (KeyMode.prompt, KeyMode.yesno):
|
if mode in (usertypes.KeyMode.prompt, usertypes.KeyMode.yesno):
|
||||||
self._prompt.txt.setText('')
|
self._prompt.txt.setText('')
|
||||||
self._prompt.lineedit.clear()
|
self._prompt.lineedit.clear()
|
||||||
self._prompt.lineedit.setEchoMode(QLineEdit.Normal)
|
self._prompt.lineedit.setEchoMode(QLineEdit.Normal)
|
||||||
@ -187,7 +188,8 @@ class Prompter:
|
|||||||
self.question.cancel()
|
self.question.cancel()
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.status.prompt.prompter', hide=True,
|
@cmdutils.register(instance='mainwindow.status.prompt.prompter', hide=True,
|
||||||
modes=[KeyMode.prompt, KeyMode.yesno])
|
modes=[usertypes.KeyMode.prompt,
|
||||||
|
usertypes.KeyMode.yesno])
|
||||||
def prompt_accept(self):
|
def prompt_accept(self):
|
||||||
"""Accept the current prompt.
|
"""Accept the current prompt.
|
||||||
|
|
||||||
@ -196,60 +198,60 @@ class Prompter:
|
|||||||
This executes the next action depending on the question mode, e.g. asks
|
This executes the next action depending on the question mode, e.g. asks
|
||||||
for the password or leaves the mode.
|
for the password or leaves the mode.
|
||||||
"""
|
"""
|
||||||
if (self.question.mode == PromptMode.user_pwd and
|
if (self.question.mode == usertypes.PromptMode.user_pwd and
|
||||||
self.question.user is None):
|
self.question.user is None):
|
||||||
# User just entered an username
|
# User just entered an username
|
||||||
self.question.user = self._prompt.lineedit.text()
|
self.question.user = self._prompt.lineedit.text()
|
||||||
self._prompt.txt.setText("Password:")
|
self._prompt.txt.setText("Password:")
|
||||||
self._prompt.lineedit.clear()
|
self._prompt.lineedit.clear()
|
||||||
self._prompt.lineedit.setEchoMode(QLineEdit.Password)
|
self._prompt.lineedit.setEchoMode(QLineEdit.Password)
|
||||||
elif self.question.mode == PromptMode.user_pwd:
|
elif self.question.mode == usertypes.PromptMode.user_pwd:
|
||||||
# User just entered a password
|
# User just entered a password
|
||||||
password = self._prompt.lineedit.text()
|
password = self._prompt.lineedit.text()
|
||||||
self.question.answer = (self.question.user, password)
|
self.question.answer = (self.question.user, password)
|
||||||
modeman.leave(KeyMode.prompt, 'prompt accept')
|
modeman.leave(usertypes.KeyMode.prompt, 'prompt accept')
|
||||||
self.question.done()
|
self.question.done()
|
||||||
elif self.question.mode == PromptMode.text:
|
elif self.question.mode == usertypes.PromptMode.text:
|
||||||
# User just entered text.
|
# User just entered text.
|
||||||
self.question.answer = self._prompt.lineedit.text()
|
self.question.answer = self._prompt.lineedit.text()
|
||||||
modeman.leave(KeyMode.prompt, 'prompt accept')
|
modeman.leave(usertypes.KeyMode.prompt, 'prompt accept')
|
||||||
self.question.done()
|
self.question.done()
|
||||||
elif self.question.mode == PromptMode.yesno:
|
elif self.question.mode == usertypes.PromptMode.yesno:
|
||||||
# User wants to accept the default of a yes/no question.
|
# User wants to accept the default of a yes/no question.
|
||||||
self.question.answer = self.question.default
|
self.question.answer = self.question.default
|
||||||
modeman.leave(KeyMode.yesno, 'yesno accept')
|
modeman.leave(usertypes.KeyMode.yesno, 'yesno accept')
|
||||||
self.question.done()
|
self.question.done()
|
||||||
elif self.question.mode == PromptMode.alert:
|
elif self.question.mode == usertypes.PromptMode.alert:
|
||||||
# User acknowledged an alert
|
# User acknowledged an alert
|
||||||
self.question.answer = None
|
self.question.answer = None
|
||||||
modeman.leave(KeyMode.prompt, 'alert accept')
|
modeman.leave(usertypes.KeyMode.prompt, 'alert accept')
|
||||||
self.question.done()
|
self.question.done()
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid question mode!")
|
raise ValueError("Invalid question mode!")
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.status.prompt.prompter', hide=True,
|
@cmdutils.register(instance='mainwindow.status.prompt.prompter', hide=True,
|
||||||
modes=[KeyMode.yesno])
|
modes=[usertypes.KeyMode.yesno])
|
||||||
def prompt_yes(self):
|
def prompt_yes(self):
|
||||||
"""Answer yes to a yes/no prompt."""
|
"""Answer yes to a yes/no prompt."""
|
||||||
if self.question.mode != PromptMode.yesno:
|
if self.question.mode != usertypes.PromptMode.yesno:
|
||||||
# We just ignore this if we don't have a yes/no question.
|
# We just ignore this if we don't have a yes/no question.
|
||||||
return
|
return
|
||||||
self.question.answer = True
|
self.question.answer = True
|
||||||
modeman.leave(KeyMode.yesno, 'yesno accept')
|
modeman.leave(usertypes.KeyMode.yesno, 'yesno accept')
|
||||||
self.question.done()
|
self.question.done()
|
||||||
|
|
||||||
@cmdutils.register(instance='mainwindow.status.prompt.prompter', hide=True,
|
@cmdutils.register(instance='mainwindow.status.prompt.prompter', hide=True,
|
||||||
modes=[KeyMode.yesno])
|
modes=[usertypes.KeyMode.yesno])
|
||||||
def prompt_no(self):
|
def prompt_no(self):
|
||||||
"""Answer no to a yes/no prompt."""
|
"""Answer no to a yes/no prompt."""
|
||||||
if self.question.mode != PromptMode.yesno:
|
if self.question.mode != usertypes.PromptMode.yesno:
|
||||||
# We just ignore this if we don't have a yes/no question.
|
# We just ignore this if we don't have a yes/no question.
|
||||||
return
|
return
|
||||||
self.question.answer = False
|
self.question.answer = False
|
||||||
modeman.leave(KeyMode.yesno, 'prompt accept')
|
modeman.leave(usertypes.KeyMode.yesno, 'prompt accept')
|
||||||
self.question.done()
|
self.question.done()
|
||||||
|
|
||||||
@pyqtSlot(Question, bool)
|
@pyqtSlot(usertypes.Question, bool)
|
||||||
def ask_question(self, question, blocking):
|
def ask_question(self, question, blocking):
|
||||||
"""Dispkay a question in the statusbar.
|
"""Dispkay a question in the statusbar.
|
||||||
|
|
||||||
@ -282,12 +284,12 @@ class Prompter:
|
|||||||
try:
|
try:
|
||||||
modeman.enter(mode, 'question asked')
|
modeman.enter(mode, 'question asked')
|
||||||
except modeman.ModeLockedError:
|
except modeman.ModeLockedError:
|
||||||
if modeman.instance().mode != KeyMode.prompt:
|
if modeman.instance().mode != usertypes.KeyMode.prompt:
|
||||||
question.abort()
|
question.abort()
|
||||||
return None
|
return None
|
||||||
modeman.instance().locked = True
|
modeman.instance().locked = True
|
||||||
if blocking:
|
if blocking:
|
||||||
loop = EventLoop()
|
loop = qtutils.EventLoop()
|
||||||
self._loops.append(loop)
|
self._loops.append(loop)
|
||||||
loop.destroyed.connect(lambda: self._loops.remove(loop))
|
loop.destroyed.connect(lambda: self._loops.remove(loop))
|
||||||
question.completed.connect(loop.quit)
|
question.completed.connect(loop.quit)
|
||||||
|
@ -21,11 +21,11 @@
|
|||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot
|
from PyQt5.QtCore import pyqtSlot
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.widgets.statusbar.textbase import TextBase
|
from qutebrowser.widgets.statusbar import textbase
|
||||||
|
|
||||||
|
|
||||||
class Text(TextBase):
|
class Text(textbase.TextBase):
|
||||||
|
|
||||||
"""Text displayed in the statusbar.
|
"""Text displayed in the statusbar.
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ from PyQt5.QtCore import Qt
|
|||||||
from PyQt5.QtWidgets import QLabel, QSizePolicy
|
from PyQt5.QtWidgets import QLabel, QSizePolicy
|
||||||
from PyQt5.QtGui import QPainter
|
from PyQt5.QtGui import QPainter
|
||||||
|
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
from qutebrowser.utils import qt as qtutils
|
||||||
|
|
||||||
|
|
||||||
class TextBase(QLabel):
|
class TextBase(QLabel):
|
||||||
@ -79,7 +79,7 @@ class TextBase(QLabel):
|
|||||||
"""Extend QLabel::resizeEvent to update the elided text afterwards."""
|
"""Extend QLabel::resizeEvent to update the elided text afterwards."""
|
||||||
super().resizeEvent(e)
|
super().resizeEvent(e)
|
||||||
size = e.size()
|
size = e.size()
|
||||||
qt_ensure_valid(size)
|
qtutils.qt_ensure_valid(size)
|
||||||
self._update_elided_text(size.width())
|
self._update_elided_text(size.width())
|
||||||
|
|
||||||
def paintEvent(self, e):
|
def paintEvent(self, e):
|
||||||
@ -90,6 +90,6 @@ class TextBase(QLabel):
|
|||||||
e.accept()
|
e.accept()
|
||||||
painter = QPainter(self)
|
painter = QPainter(self)
|
||||||
geom = self.geometry()
|
geom = self.geometry()
|
||||||
qt_ensure_valid(geom)
|
qtutils.qt_ensure_valid(geom)
|
||||||
painter.drawText(0, 0, geom.width(), geom.height(),
|
painter.drawText(0, 0, geom.width(), geom.height(),
|
||||||
self.alignment(), self._elided_text)
|
self.alignment(), self._elided_text)
|
||||||
|
@ -21,17 +21,18 @@
|
|||||||
|
|
||||||
from PyQt5.QtCore import pyqtSlot, pyqtProperty, Qt
|
from PyQt5.QtCore import pyqtSlot, pyqtProperty, Qt
|
||||||
|
|
||||||
from qutebrowser.widgets.webview import LoadStatus
|
from qutebrowser.widgets import webview
|
||||||
from qutebrowser.widgets.statusbar.textbase import TextBase
|
from qutebrowser.widgets.statusbar import textbase
|
||||||
from qutebrowser.config.style import set_register_stylesheet, get_stylesheet
|
from qutebrowser.config import style
|
||||||
from qutebrowser.utils.usertypes import enum
|
from qutebrowser.utils import usertypes
|
||||||
|
|
||||||
|
|
||||||
# Note this has entries for success/error/warn from widgets.webview:LoadStatus
|
# Note this has entries for success/error/warn from widgets.webview:LoadStatus
|
||||||
UrlType = enum('UrlType', 'success', 'error', 'warn', 'hover', 'normal')
|
UrlType = usertypes.enum('UrlType', 'success', 'error', 'warn', 'hover',
|
||||||
|
'normal')
|
||||||
|
|
||||||
|
|
||||||
class UrlText(TextBase):
|
class UrlText(textbase.TextBase):
|
||||||
|
|
||||||
"""URL displayed in the statusbar.
|
"""URL displayed in the statusbar.
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ class UrlText(TextBase):
|
|||||||
"""Override TextBase.__init__ to elide in the middle by default."""
|
"""Override TextBase.__init__ to elide in the middle by default."""
|
||||||
super().__init__(parent, Qt.ElideMiddle)
|
super().__init__(parent, Qt.ElideMiddle)
|
||||||
self.setObjectName(self.__class__.__name__)
|
self.setObjectName(self.__class__.__name__)
|
||||||
set_register_stylesheet(self)
|
style.set_register_stylesheet(self)
|
||||||
self._hover_url = None
|
self._hover_url = None
|
||||||
self._normal_url = None
|
self._normal_url = None
|
||||||
self._normal_url_type = UrlType.normal
|
self._normal_url_type = UrlType.normal
|
||||||
@ -104,7 +105,7 @@ class UrlText(TextBase):
|
|||||||
if not isinstance(val, UrlType):
|
if not isinstance(val, UrlType):
|
||||||
raise TypeError("Type {} is no UrlType member!".format(val))
|
raise TypeError("Type {} is no UrlType member!".format(val))
|
||||||
self._urltype = val
|
self._urltype = val
|
||||||
self.setStyleSheet(get_stylesheet(self.STYLESHEET))
|
self.setStyleSheet(style.get_stylesheet(self.STYLESHEET))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hover_url(self):
|
def hover_url(self):
|
||||||
@ -164,8 +165,9 @@ class UrlText(TextBase):
|
|||||||
Args:
|
Args:
|
||||||
status_str: The LoadStatus as string.
|
status_str: The LoadStatus as string.
|
||||||
"""
|
"""
|
||||||
status = LoadStatus[status_str]
|
status = webview.LoadStatus[status_str]
|
||||||
if status in (LoadStatus.success, LoadStatus.error, LoadStatus.warn):
|
if status in (webview.LoadStatus.success, webview.LoadStatus.error,
|
||||||
|
webview.LoadStatus.warn):
|
||||||
self.normal_url_type = UrlType[status_str]
|
self.normal_url_type = UrlType[status_str]
|
||||||
else:
|
else:
|
||||||
self.normal_url_type = UrlType.normal
|
self.normal_url_type = UrlType.normal
|
||||||
|
@ -19,29 +19,25 @@
|
|||||||
|
|
||||||
"""The main tabbed browser widget."""
|
"""The main tabbed browser widget."""
|
||||||
|
|
||||||
from functools import partial
|
import functools
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QSizePolicy
|
from PyQt5.QtWidgets import QSizePolicy
|
||||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QSize, QTimer
|
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QSize, QTimer
|
||||||
from PyQt5.QtGui import QIcon
|
from PyQt5.QtGui import QIcon
|
||||||
from PyQt5.QtWebKitWidgets import QWebPage
|
from PyQt5.QtWebKitWidgets import QWebPage
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser.commands import utils as cmdutils
|
||||||
import qutebrowser.keyinput.modeman as modeman
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.keyinput import modeman
|
||||||
import qutebrowser.utils.misc as utils
|
from qutebrowser.widgets import tabwidget, webview
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.browser import signalfilter, commands
|
||||||
from qutebrowser.widgets.tabwidget import TabWidget
|
from qutebrowser.utils import log, message, usertypes
|
||||||
from qutebrowser.widgets.webview import WebView
|
from qutebrowser.utils import misc as utils
|
||||||
from qutebrowser.browser.signalfilter import SignalFilter
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.browser.commands import CommandDispatcher
|
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid, QtValueError
|
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
|
||||||
from qutebrowser.utils.usertypes import KeyMode
|
|
||||||
|
|
||||||
|
|
||||||
class TabbedBrowser(TabWidget):
|
class TabbedBrowser(tabwidget.TabWidget):
|
||||||
|
|
||||||
"""A TabWidget with QWebViews inside.
|
"""A TabWidget with QWebViews inside.
|
||||||
|
|
||||||
@ -104,7 +100,7 @@ class TabbedBrowser(TabWidget):
|
|||||||
quit = pyqtSignal()
|
quit = pyqtSignal()
|
||||||
resized = pyqtSignal('QRect')
|
resized = pyqtSignal('QRect')
|
||||||
got_cmd = pyqtSignal(str)
|
got_cmd = pyqtSignal(str)
|
||||||
current_tab_changed = pyqtSignal(WebView)
|
current_tab_changed = pyqtSignal(webview.WebView)
|
||||||
title_changed = pyqtSignal(str)
|
title_changed = pyqtSignal(str)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@ -116,8 +112,8 @@ class TabbedBrowser(TabWidget):
|
|||||||
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||||
self._tabs = []
|
self._tabs = []
|
||||||
self.url_stack = []
|
self.url_stack = []
|
||||||
self._filter = SignalFilter(self)
|
self._filter = signalfilter.SignalFilter(self)
|
||||||
self.cmd = CommandDispatcher(self)
|
self.cmd = commands.CommandDispatcher(self)
|
||||||
self.last_focused = None
|
self.last_focused = None
|
||||||
self._now_focused = None
|
self._now_focused = None
|
||||||
# FIXME adjust this to font size
|
# FIXME adjust this to font size
|
||||||
@ -159,7 +155,8 @@ class TabbedBrowser(TabWidget):
|
|||||||
self._filter.create(self.cur_url_text_changed, tab))
|
self._filter.create(self.cur_url_text_changed, tab))
|
||||||
tab.load_status_changed.connect(
|
tab.load_status_changed.connect(
|
||||||
self._filter.create(self.cur_load_status_changed, tab))
|
self._filter.create(self.cur_load_status_changed, tab))
|
||||||
tab.url_text_changed.connect(partial(self.on_url_text_changed, tab))
|
tab.url_text_changed.connect(
|
||||||
|
functools.partial(self.on_url_text_changed, tab))
|
||||||
# hintmanager
|
# hintmanager
|
||||||
tab.hintmanager.hint_strings_updated.connect(self.hint_strings_updated)
|
tab.hintmanager.hint_strings_updated.connect(self.hint_strings_updated)
|
||||||
tab.hintmanager.download_get.connect(self.download_get)
|
tab.hintmanager.download_get.connect(self.download_get)
|
||||||
@ -168,13 +165,18 @@ class TabbedBrowser(TabWidget):
|
|||||||
# downloads
|
# downloads
|
||||||
page.start_download.connect(self.start_download)
|
page.start_download.connect(self.start_download)
|
||||||
# misc
|
# misc
|
||||||
tab.titleChanged.connect(partial(self.on_title_changed, tab))
|
tab.titleChanged.connect(
|
||||||
tab.iconChanged.connect(partial(self.on_icon_changed, tab))
|
functools.partial(self.on_title_changed, tab))
|
||||||
tab.loadProgress.connect(partial(self.on_load_progress, tab))
|
tab.iconChanged.connect(
|
||||||
frame.loadFinished.connect(partial(self.on_load_finished, tab))
|
functools.partial(self.on_icon_changed, tab))
|
||||||
frame.loadStarted.connect(partial(self.on_load_started, tab))
|
tab.loadProgress.connect(
|
||||||
|
functools.partial(self.on_load_progress, tab))
|
||||||
|
frame.loadFinished.connect(
|
||||||
|
functools.partial(self.on_load_finished, tab))
|
||||||
|
frame.loadStarted.connect(
|
||||||
|
functools.partial(self.on_load_started, tab))
|
||||||
page.windowCloseRequested.connect(
|
page.windowCloseRequested.connect(
|
||||||
partial(self.on_window_close_requested, tab))
|
functools.partial(self.on_window_close_requested, tab))
|
||||||
|
|
||||||
def cntwidget(self, count=None):
|
def cntwidget(self, count=None):
|
||||||
"""Return a widget based on a count/idx.
|
"""Return a widget based on a count/idx.
|
||||||
@ -208,13 +210,13 @@ class TabbedBrowser(TabWidget):
|
|||||||
"""
|
"""
|
||||||
url = self.currentWidget().cur_url
|
url = self.currentWidget().cur_url
|
||||||
try:
|
try:
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
except QtValueError as e:
|
except qtutils.QtValueError as e:
|
||||||
msg = "Current URL is invalid"
|
msg = "Current URL is invalid"
|
||||||
if e.reason:
|
if e.reason:
|
||||||
msg += " ({})".format(e.reason)
|
msg += " ({})".format(e.reason)
|
||||||
msg += "!"
|
msg += "!"
|
||||||
raise CommandError(msg)
|
raise cmdexc.CommandError(msg)
|
||||||
return url
|
return url
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
@ -264,7 +266,7 @@ class TabbedBrowser(TabWidget):
|
|||||||
if tab is self.last_focused:
|
if tab is self.last_focused:
|
||||||
self.last_focused = None
|
self.last_focused = None
|
||||||
if not tab.cur_url.isEmpty():
|
if not tab.cur_url.isEmpty():
|
||||||
qt_ensure_valid(tab.cur_url)
|
qtutils.qt_ensure_valid(tab.cur_url)
|
||||||
self.url_stack.append(tab.cur_url)
|
self.url_stack.append(tab.cur_url)
|
||||||
tab.shutdown()
|
tab.shutdown()
|
||||||
self._tabs.remove(tab)
|
self._tabs.remove(tab)
|
||||||
@ -279,7 +281,7 @@ class TabbedBrowser(TabWidget):
|
|||||||
url: The URL to open as QUrl.
|
url: The URL to open as QUrl.
|
||||||
newtab: True to open URL in a new tab, False otherwise.
|
newtab: True to open URL in a new tab, False otherwise.
|
||||||
"""
|
"""
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
if newtab:
|
if newtab:
|
||||||
self.tabopen(url, background=False)
|
self.tabopen(url, background=False)
|
||||||
else:
|
else:
|
||||||
@ -295,7 +297,7 @@ class TabbedBrowser(TabWidget):
|
|||||||
return
|
return
|
||||||
self.close_tab(tab)
|
self.close_tab(tab)
|
||||||
|
|
||||||
@pyqtSlot(WebView)
|
@pyqtSlot(webview.WebView)
|
||||||
def on_window_close_requested(self, widget):
|
def on_window_close_requested(self, widget):
|
||||||
"""Close a tab with a widget given."""
|
"""Close a tab with a widget given."""
|
||||||
self.close_tab(widget)
|
self.close_tab(widget)
|
||||||
@ -322,9 +324,9 @@ class TabbedBrowser(TabWidget):
|
|||||||
The opened WebView instance.
|
The opened WebView instance.
|
||||||
"""
|
"""
|
||||||
if url is not None:
|
if url is not None:
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
log.webview.debug("Creating new tab with URL {}".format(url))
|
log.webview.debug("Creating new tab with URL {}".format(url))
|
||||||
tab = WebView(self)
|
tab = webview.WebView(self)
|
||||||
self._connect_tab_signals(tab)
|
self._connect_tab_signals(tab)
|
||||||
self._tabs.append(tab)
|
self._tabs.append(tab)
|
||||||
if explicit:
|
if explicit:
|
||||||
@ -440,10 +442,10 @@ class TabbedBrowser(TabWidget):
|
|||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_cur_load_started(self):
|
def on_cur_load_started(self):
|
||||||
"""Leave insert/hint mode when loading started."""
|
"""Leave insert/hint mode when loading started."""
|
||||||
modeman.maybe_leave(KeyMode.insert, 'load started')
|
modeman.maybe_leave(usertypes.KeyMode.insert, 'load started')
|
||||||
modeman.maybe_leave(KeyMode.hint, 'load started')
|
modeman.maybe_leave(usertypes.KeyMode.hint, 'load started')
|
||||||
|
|
||||||
@pyqtSlot(WebView, str)
|
@pyqtSlot(webview.WebView, str)
|
||||||
def on_title_changed(self, tab, text):
|
def on_title_changed(self, tab, text):
|
||||||
"""Set the title of a tab.
|
"""Set the title of a tab.
|
||||||
|
|
||||||
@ -470,7 +472,7 @@ class TabbedBrowser(TabWidget):
|
|||||||
if idx == self.currentIndex():
|
if idx == self.currentIndex():
|
||||||
self.title_changed.emit('{} - qutebrowser'.format(text))
|
self.title_changed.emit('{} - qutebrowser'.format(text))
|
||||||
|
|
||||||
@pyqtSlot(WebView, str)
|
@pyqtSlot(webview.WebView, str)
|
||||||
def on_url_text_changed(self, tab, url):
|
def on_url_text_changed(self, tab, url):
|
||||||
"""Set the new URL as title if there's no title yet.
|
"""Set the new URL as title if there's no title yet.
|
||||||
|
|
||||||
@ -490,7 +492,7 @@ class TabbedBrowser(TabWidget):
|
|||||||
if not self.tabText(idx):
|
if not self.tabText(idx):
|
||||||
self.setTabText(idx, url)
|
self.setTabText(idx, url)
|
||||||
|
|
||||||
@pyqtSlot(WebView)
|
@pyqtSlot(webview.WebView)
|
||||||
def on_icon_changed(self, tab):
|
def on_icon_changed(self, tab):
|
||||||
"""Set the icon of a tab.
|
"""Set the icon of a tab.
|
||||||
|
|
||||||
@ -512,10 +514,10 @@ class TabbedBrowser(TabWidget):
|
|||||||
return
|
return
|
||||||
self.setTabIcon(idx, tab.icon())
|
self.setTabIcon(idx, tab.icon())
|
||||||
|
|
||||||
@pyqtSlot(KeyMode)
|
@pyqtSlot(usertypes.KeyMode)
|
||||||
def on_mode_left(self, mode):
|
def on_mode_left(self, mode):
|
||||||
"""Give focus to current tab if command mode was left."""
|
"""Give focus to current tab if command mode was left."""
|
||||||
if mode == KeyMode.command:
|
if mode == usertypes.KeyMode.command:
|
||||||
self.currentWidget().setFocus()
|
self.currentWidget().setFocus()
|
||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
@ -523,7 +525,7 @@ class TabbedBrowser(TabWidget):
|
|||||||
"""Set last_focused and leave hinting mode when focus changed."""
|
"""Set last_focused and leave hinting mode when focus changed."""
|
||||||
tab = self.widget(idx)
|
tab = self.widget(idx)
|
||||||
tab.setFocus()
|
tab.setFocus()
|
||||||
modeman.maybe_leave(KeyMode.hint, 'tab changed')
|
modeman.maybe_leave(usertypes.KeyMode.hint, 'tab changed')
|
||||||
self.last_focused = self._now_focused
|
self.last_focused = self._now_focused
|
||||||
self._now_focused = tab
|
self._now_focused = tab
|
||||||
self.current_tab_changed.emit(tab)
|
self.current_tab_changed.emit(tab)
|
||||||
|
@ -32,8 +32,8 @@ from PyQt5.QtWidgets import (QTabWidget, QTabBar, QSizePolicy, QCommonStyle,
|
|||||||
QApplication)
|
QApplication)
|
||||||
from PyQt5.QtGui import QIcon, QPalette, QColor
|
from PyQt5.QtGui import QIcon, QPalette, QColor
|
||||||
|
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
from qutebrowser.utils import qt as qtutils
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
|
|
||||||
|
|
||||||
PM_TabBarPadding = QStyle.PM_CustomBase
|
PM_TabBarPadding = QStyle.PM_CustomBase
|
||||||
@ -211,7 +211,7 @@ class TabBar(QTabBar):
|
|||||||
# If we *do* have enough space, tabs should occupy the whole window
|
# If we *do* have enough space, tabs should occupy the whole window
|
||||||
# width.
|
# width.
|
||||||
size = QSize(self.width() / self.count(), height)
|
size = QSize(self.width() / self.count(), height)
|
||||||
qt_ensure_valid(size)
|
qtutils.qt_ensure_valid(size)
|
||||||
return size
|
return size
|
||||||
|
|
||||||
def paintEvent(self, _e):
|
def paintEvent(self, _e):
|
||||||
@ -311,7 +311,7 @@ class TabBarStyle(QCommonStyle):
|
|||||||
elif element == QStyle.CE_TabBarTabLabel:
|
elif element == QStyle.CE_TabBarTabLabel:
|
||||||
text_rect, icon_rect = self._tab_layout(opt)
|
text_rect, icon_rect = self._tab_layout(opt)
|
||||||
if not opt.icon.isNull():
|
if not opt.icon.isNull():
|
||||||
qt_ensure_valid(icon_rect)
|
qtutils.qt_ensure_valid(icon_rect)
|
||||||
icon_mode = (QIcon.Normal if opt.state & QStyle.State_Enabled
|
icon_mode = (QIcon.Normal if opt.state & QStyle.State_Enabled
|
||||||
else QIcon.Disabled)
|
else QIcon.Disabled)
|
||||||
icon_state = (QIcon.On if opt.state & QStyle.State_Selected
|
icon_state = (QIcon.On if opt.state & QStyle.State_Selected
|
||||||
@ -382,7 +382,7 @@ class TabBarStyle(QCommonStyle):
|
|||||||
padding = self.pixelMetric(PM_TabBarPadding, opt)
|
padding = self.pixelMetric(PM_TabBarPadding, opt)
|
||||||
icon_rect = QRect()
|
icon_rect = QRect()
|
||||||
text_rect = QRect(opt.rect)
|
text_rect = QRect(opt.rect)
|
||||||
qt_ensure_valid(text_rect)
|
qtutils.qt_ensure_valid(text_rect)
|
||||||
indicator_width = config.get('tabs', 'indicator-width')
|
indicator_width = config.get('tabs', 'indicator-width')
|
||||||
text_rect.adjust(padding, 0, 0, 0)
|
text_rect.adjust(padding, 0, 0, 0)
|
||||||
if indicator_width != 0:
|
if indicator_width != 0:
|
||||||
@ -419,5 +419,5 @@ class TabBarStyle(QCommonStyle):
|
|||||||
text_rect.center().y() - tab_icon_size.height() / 2,
|
text_rect.center().y() - tab_icon_size.height() / 2,
|
||||||
tab_icon_size.width(), tab_icon_size.height())
|
tab_icon_size.width(), tab_icon_size.height())
|
||||||
icon_rect = self._style.visualRect(opt.direction, opt.rect, icon_rect)
|
icon_rect = self._style.visualRect(opt.direction, opt.rect, icon_rect)
|
||||||
qt_ensure_valid(icon_rect)
|
qtutils.qt_ensure_valid(icon_rect)
|
||||||
return icon_rect
|
return icon_rect
|
||||||
|
@ -24,21 +24,17 @@ from PyQt5.QtWidgets import QApplication
|
|||||||
from PyQt5.QtWebKit import QWebSettings
|
from PyQt5.QtWebKit import QWebSettings
|
||||||
from PyQt5.QtWebKitWidgets import QWebView, QWebPage
|
from PyQt5.QtWebKitWidgets import QWebView, QWebPage
|
||||||
|
|
||||||
import qutebrowser.config.config as config
|
from qutebrowser.config import config
|
||||||
import qutebrowser.keyinput.modeman as modeman
|
from qutebrowser.keyinput import modeman
|
||||||
import qutebrowser.utils.message as message
|
from qutebrowser.utils import message, webelem, log, usertypes
|
||||||
import qutebrowser.utils.webelem as webelem
|
from qutebrowser.utils import misc as utils
|
||||||
import qutebrowser.utils.log as log
|
from qutebrowser.utils import qt as qtutils
|
||||||
from qutebrowser.utils.misc import elide
|
from qutebrowser.browser import webpage, hints
|
||||||
from qutebrowser.utils.qt import qt_ensure_valid
|
from qutebrowser.commands import exceptions as cmdexc
|
||||||
from qutebrowser.browser.webpage import BrowserPage
|
|
||||||
from qutebrowser.browser.hints import HintManager
|
|
||||||
from qutebrowser.utils.usertypes import (NeighborList, ClickTarget, KeyMode,
|
|
||||||
enum)
|
|
||||||
from qutebrowser.commands.exceptions import CommandError
|
|
||||||
|
|
||||||
|
|
||||||
LoadStatus = enum('LoadStatus', 'none', 'success', 'error', 'warn', 'loading')
|
LoadStatus = usertypes.enum('LoadStatus', 'none', 'success', 'error', 'warn',
|
||||||
|
'loading')
|
||||||
|
|
||||||
|
|
||||||
class WebView(QWebView):
|
class WebView(QWebView):
|
||||||
@ -93,7 +89,7 @@ class WebView(QWebView):
|
|||||||
self.statusbar_message = ''
|
self.statusbar_message = ''
|
||||||
self._old_scroll_pos = (-1, -1)
|
self._old_scroll_pos = (-1, -1)
|
||||||
self._open_target = None
|
self._open_target = None
|
||||||
self.open_target = ClickTarget.normal
|
self.open_target = usertypes.ClickTarget.normal
|
||||||
self._force_open_target = None
|
self._force_open_target = None
|
||||||
self._zoom = None
|
self._zoom = None
|
||||||
self._has_ssl_errors = False
|
self._has_ssl_errors = False
|
||||||
@ -101,9 +97,9 @@ class WebView(QWebView):
|
|||||||
self._cur_url = None
|
self._cur_url = None
|
||||||
self.cur_url = QUrl()
|
self.cur_url = QUrl()
|
||||||
self.progress = 0
|
self.progress = 0
|
||||||
self._page = BrowserPage(self)
|
self._page = webpage.BrowserPage(self)
|
||||||
self.setPage(self._page)
|
self.setPage(self._page)
|
||||||
self.hintmanager = HintManager(self)
|
self.hintmanager = hints.HintManager(self)
|
||||||
self.hintmanager.mouse_event.connect(self.on_mouse_event)
|
self.hintmanager.mouse_event.connect(self.on_mouse_event)
|
||||||
self.hintmanager.set_open_target.connect(self.set_force_open_target)
|
self.hintmanager.set_open_target.connect(self.set_force_open_target)
|
||||||
self._page.linkHovered.connect(self.linkHovered)
|
self._page.linkHovered.connect(self.linkHovered)
|
||||||
@ -120,7 +116,7 @@ class WebView(QWebView):
|
|||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
url = self.url().toDisplayString()
|
url = self.url().toDisplayString()
|
||||||
return "WebView(url='{}')".format(elide(url, 50))
|
return "WebView(url='{}')".format(utils.elide(url, 50))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def open_target(self):
|
def open_target(self):
|
||||||
@ -130,7 +126,7 @@ class WebView(QWebView):
|
|||||||
@open_target.setter
|
@open_target.setter
|
||||||
def open_target(self, val):
|
def open_target(self, val):
|
||||||
"""Setter for open_target to do type checking."""
|
"""Setter for open_target to do type checking."""
|
||||||
if not isinstance(val, ClickTarget):
|
if not isinstance(val, usertypes.ClickTarget):
|
||||||
raise TypeError("Target {} is no ClickTarget member!".format(val))
|
raise TypeError("Target {} is no ClickTarget member!".format(val))
|
||||||
self._open_target = val
|
self._open_target = val
|
||||||
|
|
||||||
@ -172,9 +168,10 @@ class WebView(QWebView):
|
|||||||
|
|
||||||
def _init_neighborlist(self):
|
def _init_neighborlist(self):
|
||||||
"""Initialize the _zoom neighborlist."""
|
"""Initialize the _zoom neighborlist."""
|
||||||
self._zoom = NeighborList(config.get('ui', 'zoom-levels'),
|
levels = config.get('ui', 'zoom-levels')
|
||||||
default=config.get('ui', 'default-zoom'),
|
default = config.get('ui', 'default-zoom')
|
||||||
mode=NeighborList.Modes.block)
|
self._zoom = usertypes.NeighborList(
|
||||||
|
levels, default, mode=usertypes.NeighborList.Modes.block)
|
||||||
|
|
||||||
def _mousepress_backforward(self, e):
|
def _mousepress_backforward(self, e):
|
||||||
"""Handle back/forward mouse button presses.
|
"""Handle back/forward mouse button presses.
|
||||||
@ -186,13 +183,13 @@ class WebView(QWebView):
|
|||||||
# Back button on mice which have it.
|
# Back button on mice which have it.
|
||||||
try:
|
try:
|
||||||
self.go_back()
|
self.go_back()
|
||||||
except CommandError as ex:
|
except cmdexc.CommandError as ex:
|
||||||
message.error(ex, immediately=True)
|
message.error(ex, immediately=True)
|
||||||
elif e.button() == Qt.XButton2:
|
elif e.button() == Qt.XButton2:
|
||||||
# Forward button on mice which have it.
|
# Forward button on mice which have it.
|
||||||
try:
|
try:
|
||||||
self.go_forward()
|
self.go_forward()
|
||||||
except CommandError as ex:
|
except cmdexc.CommandError as ex:
|
||||||
message.error(ex, immediately=True)
|
message.error(ex, immediately=True)
|
||||||
|
|
||||||
def _mousepress_insertmode(self, e):
|
def _mousepress_insertmode(self, e):
|
||||||
@ -233,11 +230,11 @@ class WebView(QWebView):
|
|||||||
elif ((hitresult.isContentEditable() and webelem.is_writable(elem)) or
|
elif ((hitresult.isContentEditable() and webelem.is_writable(elem)) or
|
||||||
webelem.is_editable(elem)):
|
webelem.is_editable(elem)):
|
||||||
log.mouse.debug("Clicked editable element!")
|
log.mouse.debug("Clicked editable element!")
|
||||||
modeman.maybe_enter(KeyMode.insert, 'click')
|
modeman.maybe_enter(usertypes.KeyMode.insert, 'click')
|
||||||
else:
|
else:
|
||||||
log.mouse.debug("Clicked non-editable element!")
|
log.mouse.debug("Clicked non-editable element!")
|
||||||
if config.get('input', 'auto-leave-insert-mode'):
|
if config.get('input', 'auto-leave-insert-mode'):
|
||||||
modeman.maybe_leave(KeyMode.insert, 'click')
|
modeman.maybe_leave(usertypes.KeyMode.insert, 'click')
|
||||||
|
|
||||||
def mouserelease_insertmode(self):
|
def mouserelease_insertmode(self):
|
||||||
"""If we have an insertmode check scheduled, handle it."""
|
"""If we have an insertmode check scheduled, handle it."""
|
||||||
@ -247,11 +244,11 @@ class WebView(QWebView):
|
|||||||
elem = webelem.focus_elem(self.page().currentFrame())
|
elem = webelem.focus_elem(self.page().currentFrame())
|
||||||
if webelem.is_editable(elem):
|
if webelem.is_editable(elem):
|
||||||
log.mouse.debug("Clicked editable element (delayed)!")
|
log.mouse.debug("Clicked editable element (delayed)!")
|
||||||
modeman.maybe_enter(KeyMode.insert, 'click-delayed')
|
modeman.maybe_enter(usertypes.KeyMode.insert, 'click-delayed')
|
||||||
else:
|
else:
|
||||||
log.mouse.debug("Clicked non-editable element (delayed)!")
|
log.mouse.debug("Clicked non-editable element (delayed)!")
|
||||||
if config.get('input', 'auto-leave-insert-mode'):
|
if config.get('input', 'auto-leave-insert-mode'):
|
||||||
modeman.maybe_leave(KeyMode.insert, 'click-delayed')
|
modeman.maybe_leave(usertypes.KeyMode.insert, 'click-delayed')
|
||||||
|
|
||||||
def _mousepress_opentarget(self, e):
|
def _mousepress_opentarget(self, e):
|
||||||
"""Set the open target when something was clicked.
|
"""Set the open target when something was clicked.
|
||||||
@ -267,13 +264,13 @@ class WebView(QWebView):
|
|||||||
elif (e.button() == Qt.MidButton or
|
elif (e.button() == Qt.MidButton or
|
||||||
e.modifiers() & Qt.ControlModifier):
|
e.modifiers() & Qt.ControlModifier):
|
||||||
if config.get('tabs', 'background-tabs'):
|
if config.get('tabs', 'background-tabs'):
|
||||||
self.open_target = ClickTarget.tab_bg
|
self.open_target = usertypes.ClickTarget.tab_bg
|
||||||
else:
|
else:
|
||||||
self.open_target = ClickTarget.tab
|
self.open_target = usertypes.ClickTarget.tab
|
||||||
log.mouse.debug("Middle click, setting target: {}".format(
|
log.mouse.debug("Middle click, setting target: {}".format(
|
||||||
self.open_target))
|
self.open_target))
|
||||||
else:
|
else:
|
||||||
self.open_target = ClickTarget.normal
|
self.open_target = usertypes.ClickTarget.normal
|
||||||
log.mouse.debug("Normal click, setting normal target")
|
log.mouse.debug("Normal click, setting normal target")
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
@ -304,7 +301,7 @@ class WebView(QWebView):
|
|||||||
Emit:
|
Emit:
|
||||||
titleChanged
|
titleChanged
|
||||||
"""
|
"""
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
urlstr = url.toDisplayString()
|
urlstr = url.toDisplayString()
|
||||||
log.webview.debug("New title: {}".format(urlstr))
|
log.webview.debug("New title: {}".format(urlstr))
|
||||||
self.titleChanged.emit(urlstr)
|
self.titleChanged.emit(urlstr)
|
||||||
@ -321,7 +318,7 @@ class WebView(QWebView):
|
|||||||
if fuzzyval:
|
if fuzzyval:
|
||||||
self._zoom.fuzzyval = int(perc)
|
self._zoom.fuzzyval = int(perc)
|
||||||
if perc < 0:
|
if perc < 0:
|
||||||
raise CommandError("Can't zoom {}%!".format(perc))
|
raise cmdexc.CommandError("Can't zoom {}%!".format(perc))
|
||||||
self.setZoomFactor(float(perc) / 100)
|
self.setZoomFactor(float(perc) / 100)
|
||||||
message.info("Zoom level: {}%".format(perc))
|
message.info("Zoom level: {}%".format(perc))
|
||||||
|
|
||||||
@ -349,19 +346,19 @@ class WebView(QWebView):
|
|||||||
if self.page().history().canGoBack():
|
if self.page().history().canGoBack():
|
||||||
self.back()
|
self.back()
|
||||||
else:
|
else:
|
||||||
raise CommandError("At beginning of history.")
|
raise cmdexc.CommandError("At beginning of history.")
|
||||||
|
|
||||||
def go_forward(self):
|
def go_forward(self):
|
||||||
"""Go forward a page in the history."""
|
"""Go forward a page in the history."""
|
||||||
if self.page().history().canGoForward():
|
if self.page().history().canGoForward():
|
||||||
self.forward()
|
self.forward()
|
||||||
else:
|
else:
|
||||||
raise CommandError("At end of history.")
|
raise cmdexc.CommandError("At end of history.")
|
||||||
|
|
||||||
@pyqtSlot('QUrl')
|
@pyqtSlot('QUrl')
|
||||||
def on_url_changed(self, url):
|
def on_url_changed(self, url):
|
||||||
"""Update cur_url when URL has changed."""
|
"""Update cur_url when URL has changed."""
|
||||||
qt_ensure_valid(url)
|
qtutils.qt_ensure_valid(url)
|
||||||
self.cur_url = url
|
self.cur_url = url
|
||||||
|
|
||||||
@pyqtSlot(str, str)
|
@pyqtSlot(str, str)
|
||||||
@ -394,7 +391,7 @@ class WebView(QWebView):
|
|||||||
self.load_status = LoadStatus.error
|
self.load_status = LoadStatus.error
|
||||||
if not config.get('input', 'auto-insert-mode'):
|
if not config.get('input', 'auto-insert-mode'):
|
||||||
return
|
return
|
||||||
if modeman.instance().mode == KeyMode.insert or not ok:
|
if modeman.instance().mode == usertypes.KeyMode.insert or not ok:
|
||||||
return
|
return
|
||||||
frame = self.page().currentFrame()
|
frame = self.page().currentFrame()
|
||||||
elem = frame.findFirstElement(':focus')
|
elem = frame.findFirstElement(':focus')
|
||||||
@ -402,7 +399,7 @@ class WebView(QWebView):
|
|||||||
if elem.isNull():
|
if elem.isNull():
|
||||||
log.webview.debug("Focused element is null!")
|
log.webview.debug("Focused element is null!")
|
||||||
elif webelem.is_editable(elem):
|
elif webelem.is_editable(elem):
|
||||||
modeman.maybe_enter(KeyMode.insert, 'load finished')
|
modeman.maybe_enter(usertypes.KeyMode.insert, 'load finished')
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def set_force_open_target(self, target):
|
def set_force_open_target(self, target):
|
||||||
@ -411,7 +408,7 @@ class WebView(QWebView):
|
|||||||
Args:
|
Args:
|
||||||
target: A string to set self._force_open_target to.
|
target: A string to set self._force_open_target to.
|
||||||
"""
|
"""
|
||||||
t = getattr(ClickTarget, target)
|
t = getattr(usertypes.ClickTarget, target)
|
||||||
log.webview.debug("Setting force target to {}/{}".format(target, t))
|
log.webview.debug("Setting force target to {}/{}".format(target, t))
|
||||||
self._force_open_target = t
|
self._force_open_target = t
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ import os.path
|
|||||||
import sys
|
import sys
|
||||||
import glob
|
import glob
|
||||||
import shutil
|
import shutil
|
||||||
from fnmatch import fnmatch
|
import fnmatch
|
||||||
|
|
||||||
|
|
||||||
recursive_lint = ('__pycache__', '*.pyc')
|
recursive_lint = ('__pycache__', '*.pyc')
|
||||||
@ -47,11 +47,17 @@ def remove(path):
|
|||||||
os.remove(path)
|
os.remove(path)
|
||||||
|
|
||||||
|
|
||||||
for elem in lint:
|
def main():
|
||||||
for f in glob.glob(elem):
|
"""Clean up lint in the current dir."""
|
||||||
remove(f)
|
for elem in lint:
|
||||||
|
for f in glob.glob(elem):
|
||||||
|
remove(f)
|
||||||
|
|
||||||
|
for root, _dirs, _files in os.walk(os.getcwd()):
|
||||||
|
path = os.path.basename(root)
|
||||||
|
if any([fnmatch.fnmatch(path, e) for e in recursive_lint]):
|
||||||
|
remove(root)
|
||||||
|
|
||||||
|
|
||||||
for root, dirs, files in os.walk(os.getcwd()):
|
if __name__ == '__main__':
|
||||||
if any([fnmatch(os.path.basename(root), e) for e in recursive_lint]):
|
main()
|
||||||
remove(root)
|
|
||||||
|
@ -27,12 +27,12 @@ Builds a standalone executable.
|
|||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
import sys
|
||||||
from distutils.sysconfig import get_python_lib
|
import distutils
|
||||||
|
|
||||||
from cx_Freeze import setup, Executable
|
import cx_Freeze as cx
|
||||||
|
|
||||||
sys.path.insert(0, os.getcwd())
|
sys.path.insert(0, os.getcwd())
|
||||||
from scripts.setupcommon import setupdata, write_git_file
|
from scripts import setupcommon
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -46,7 +46,8 @@ def get_egl_path():
|
|||||||
"""Get the path for PyQt5's libEGL.dll."""
|
"""Get the path for PyQt5's libEGL.dll."""
|
||||||
if not sys.platform.startswith('win'):
|
if not sys.platform.startswith('win'):
|
||||||
return None
|
return None
|
||||||
return os.path.join(get_python_lib(), r'PyQt5\libEGL.dll')
|
return os.path.join(distutils.sysconfig.get_python_lib(),
|
||||||
|
r'PyQt5\libEGL.dll')
|
||||||
|
|
||||||
build_exe_options = {
|
build_exe_options = {
|
||||||
'include_files': [
|
'include_files': [
|
||||||
@ -69,20 +70,20 @@ bdist_msi_options = {
|
|||||||
|
|
||||||
base = 'Win32GUI' if sys.platform.startswith('win') else None
|
base = 'Win32GUI' if sys.platform.startswith('win') else None
|
||||||
|
|
||||||
executable = Executable('qutebrowser/__main__.py', base=base,
|
executable = cx.Executable('qutebrowser/__main__.py', base=base,
|
||||||
targetName='qutebrowser.exe',
|
targetName='qutebrowser.exe',
|
||||||
shortcutName='qutebrowser',
|
shortcutName='qutebrowser',
|
||||||
shortcutDir='ProgramMenuFolder')
|
shortcutDir='ProgramMenuFolder')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
write_git_file()
|
setupcommon.write_git_file()
|
||||||
setup(
|
cx.setup(
|
||||||
executables=[executable],
|
executables=[executable],
|
||||||
options={
|
options={
|
||||||
'build_exe': build_exe_options,
|
'build_exe': build_exe_options,
|
||||||
'bdist_msi': bdist_msi_options,
|
'bdist_msi': bdist_msi_options,
|
||||||
},
|
},
|
||||||
**setupdata
|
**setupcommon.setupdata
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
if BASEDIR is not None:
|
if BASEDIR is not None:
|
||||||
|
@ -27,18 +27,18 @@ import html
|
|||||||
import shutil
|
import shutil
|
||||||
import inspect
|
import inspect
|
||||||
import subprocess
|
import subprocess
|
||||||
from collections import Counter, OrderedDict
|
import collections
|
||||||
from tempfile import mkstemp
|
import tempfile
|
||||||
|
|
||||||
sys.path.insert(0, os.getcwd())
|
sys.path.insert(0, os.getcwd())
|
||||||
|
|
||||||
import qutebrowser
|
import qutebrowser
|
||||||
# We import qutebrowser.app so all @cmdutils-register decorators are run.
|
# We import qutebrowser.app so all @cmdutils-register decorators are run.
|
||||||
import qutebrowser.app
|
import qutebrowser.app
|
||||||
import qutebrowser.commands.utils as cmdutils
|
from qutebrowser import qutebrowser as qutequtebrowser
|
||||||
import qutebrowser.config.configdata as configdata
|
from qutebrowser.commands import utils as cmdutils
|
||||||
import qutebrowser.qutebrowser as qutequtebrowser
|
from qutebrowser.config import configdata
|
||||||
from qutebrowser.utils.usertypes import enum
|
from qutebrowser.utils import usertypes
|
||||||
|
|
||||||
|
|
||||||
def _open_file(name, mode='w'):
|
def _open_file(name, mode='w'):
|
||||||
@ -58,8 +58,9 @@ def _parse_docstring(func): # noqa
|
|||||||
A (short_desc, long_desc, arg_descs) tuple.
|
A (short_desc, long_desc, arg_descs) tuple.
|
||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
State = enum('State', 'short', 'desc', # pylint: disable=invalid-name
|
State = usertypes.enum('State', 'short', # pylint: disable=invalid-name
|
||||||
'desc_hidden', 'arg_start', 'arg_inside', 'misc')
|
'desc', 'desc_hidden', 'arg_start', 'arg_inside',
|
||||||
|
'misc')
|
||||||
doc = inspect.getdoc(func)
|
doc = inspect.getdoc(func)
|
||||||
lines = doc.splitlines()
|
lines = doc.splitlines()
|
||||||
|
|
||||||
@ -67,7 +68,7 @@ def _parse_docstring(func): # noqa
|
|||||||
|
|
||||||
short_desc = []
|
short_desc = []
|
||||||
long_desc = []
|
long_desc = []
|
||||||
arg_descs = OrderedDict()
|
arg_descs = collections.OrderedDict()
|
||||||
cur_arg_name = None
|
cur_arg_name = None
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
@ -385,7 +386,7 @@ def generate_settings(f):
|
|||||||
def _get_authors():
|
def _get_authors():
|
||||||
"""Get a list of authors based on git commit logs."""
|
"""Get a list of authors based on git commit logs."""
|
||||||
commits = subprocess.check_output(['git', 'log', '--format=%aN'])
|
commits = subprocess.check_output(['git', 'log', '--format=%aN'])
|
||||||
cnt = Counter(commits.decode('utf-8').splitlines())
|
cnt = collections.Counter(commits.decode('utf-8').splitlines())
|
||||||
return sorted(cnt, key=lambda k: cnt[k])
|
return sorted(cnt, key=lambda k: cnt[k])
|
||||||
|
|
||||||
|
|
||||||
@ -442,7 +443,7 @@ def generate_manpage_resources(f):
|
|||||||
|
|
||||||
def regenerate_authors(filename):
|
def regenerate_authors(filename):
|
||||||
"""Re-generate the authors inside README based on the commits made."""
|
"""Re-generate the authors inside README based on the commits made."""
|
||||||
oshandle, tmpname = mkstemp()
|
oshandle, tmpname = tempfile.mkstemp()
|
||||||
with _open_file(filename, mode='r') as infile, \
|
with _open_file(filename, mode='r') as infile, \
|
||||||
_open_file(oshandle, mode='w') as temp:
|
_open_file(oshandle, mode='w') as temp:
|
||||||
ignore = False
|
ignore = False
|
||||||
|
@ -20,18 +20,17 @@
|
|||||||
"""Custom astroid checker for config calls."""
|
"""Custom astroid checker for config calls."""
|
||||||
|
|
||||||
import astroid
|
import astroid
|
||||||
from pylint.interfaces import IAstroidChecker
|
from pylint import interfaces, checkers
|
||||||
from pylint.checkers import BaseChecker
|
|
||||||
from pylint.checkers import utils
|
from pylint.checkers import utils
|
||||||
|
|
||||||
import qutebrowser.config.configdata as configdata
|
from qutebrowser.config import configdata
|
||||||
|
|
||||||
|
|
||||||
class ConfigChecker(BaseChecker):
|
class ConfigChecker(checkers.BaseChecker):
|
||||||
|
|
||||||
"""Custom astroid checker for config calls."""
|
"""Custom astroid checker for config calls."""
|
||||||
|
|
||||||
__implements__ = IAstroidChecker
|
__implements__ = interfaces.IAstroidChecker
|
||||||
name = 'config'
|
name = 'config'
|
||||||
msgs = {
|
msgs = {
|
||||||
'E0000': ('"%s -> %s" is no valid config option.', 'bad-config-call',
|
'E0000': ('"%s -> %s" is no valid config option.', 'bad-config-call',
|
||||||
|
@ -18,15 +18,14 @@
|
|||||||
|
|
||||||
"""Checker for CRLF in files."""
|
"""Checker for CRLF in files."""
|
||||||
|
|
||||||
from pylint.interfaces import IRawChecker
|
from pylint import interfaces, checkers
|
||||||
from pylint.checkers import BaseChecker
|
|
||||||
|
|
||||||
|
|
||||||
class CrlfChecker(BaseChecker):
|
class CrlfChecker(checkers.BaseChecker):
|
||||||
|
|
||||||
"""Check for CRLF in files."""
|
"""Check for CRLF in files."""
|
||||||
|
|
||||||
__implements__ = IRawChecker
|
__implements__ = interfaces.IRawChecker
|
||||||
|
|
||||||
name = 'crlf'
|
name = 'crlf'
|
||||||
msgs = {'W9001': ('Uses CRLFs', 'crlf', None)}
|
msgs = {'W9001': ('Uses CRLFs', 'crlf', None)}
|
||||||
|
@ -20,15 +20,14 @@
|
|||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
from pylint.interfaces import IRawChecker
|
from pylint import interfaces, checkers
|
||||||
from pylint.checkers import BaseChecker
|
|
||||||
|
|
||||||
|
|
||||||
class ModelineChecker(BaseChecker):
|
class ModelineChecker(checkers.BaseChecker):
|
||||||
|
|
||||||
"""Check for vim modelines in files."""
|
"""Check for vim modelines in files."""
|
||||||
|
|
||||||
__implements__ = IRawChecker
|
__implements__ = interfaces.IRawChecker
|
||||||
|
|
||||||
name = 'modeline'
|
name = 'modeline'
|
||||||
msgs = {'W9002': ('Does not have vim modeline', 'modeline-missing', None),
|
msgs = {'W9002': ('Does not have vim modeline', 'modeline-missing', None),
|
||||||
|
@ -20,16 +20,15 @@
|
|||||||
"""Make sure open() has an encoding set."""
|
"""Make sure open() has an encoding set."""
|
||||||
|
|
||||||
import astroid
|
import astroid
|
||||||
from pylint.interfaces import IAstroidChecker
|
from pylint import interfaces, checkers
|
||||||
from pylint.checkers import BaseChecker
|
|
||||||
from pylint.checkers import utils
|
from pylint.checkers import utils
|
||||||
|
|
||||||
|
|
||||||
class OpenEncodingChecker(BaseChecker):
|
class OpenEncodingChecker(checkers.BaseChecker):
|
||||||
|
|
||||||
"""Checker to check open() has an encoding set."""
|
"""Checker to check open() has an encoding set."""
|
||||||
|
|
||||||
__implements__ = IAstroidChecker
|
__implements__ = interfaces.IAstroidChecker
|
||||||
name = 'open-encoding'
|
name = 'open-encoding'
|
||||||
|
|
||||||
msgs = {
|
msgs = {
|
||||||
|
@ -38,13 +38,13 @@ import logging
|
|||||||
import tokenize
|
import tokenize
|
||||||
import configparser
|
import configparser
|
||||||
import argparse
|
import argparse
|
||||||
from collections import OrderedDict
|
import collections
|
||||||
from functools import partial
|
import functools
|
||||||
from contextlib import contextmanager
|
import contextlib
|
||||||
|
|
||||||
import colorama as col
|
import colorama as col
|
||||||
import pep257
|
import pep257
|
||||||
from pkg_resources import load_entry_point, DistributionNotFound
|
import pkg_resources as pkg
|
||||||
|
|
||||||
|
|
||||||
sys.path.insert(0, os.getcwd())
|
sys.path.insert(0, os.getcwd())
|
||||||
@ -59,7 +59,7 @@ config = configparser.ConfigParser()
|
|||||||
config.read('.run_checks')
|
config.read('.run_checks')
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextlib.contextmanager
|
||||||
def _adjusted_pythonpath(name):
|
def _adjusted_pythonpath(name):
|
||||||
"""Adjust PYTHONPATH for pylint."""
|
"""Adjust PYTHONPATH for pylint."""
|
||||||
if name == 'pylint':
|
if name == 'pylint':
|
||||||
@ -82,7 +82,7 @@ def _run_distutils(name, args):
|
|||||||
"""Run a checker via its distutils entry point."""
|
"""Run a checker via its distutils entry point."""
|
||||||
sys.argv = [name] + args
|
sys.argv = [name] + args
|
||||||
try:
|
try:
|
||||||
ep = load_entry_point(name, 'console_scripts', name)
|
ep = pkg.load_entry_point(name, 'console_scripts', name)
|
||||||
ep()
|
ep()
|
||||||
except SystemExit as e:
|
except SystemExit as e:
|
||||||
return e.code
|
return e.code
|
||||||
@ -114,7 +114,7 @@ def run(name, target=None):
|
|||||||
with _adjusted_pythonpath(name):
|
with _adjusted_pythonpath(name):
|
||||||
try:
|
try:
|
||||||
status = _run_distutils(name, args)
|
status = _run_distutils(name, args)
|
||||||
except DistributionNotFound:
|
except pkg.DistributionNotFound:
|
||||||
status = _run_subprocess(name, args)
|
status = _run_subprocess(name, args)
|
||||||
print()
|
print()
|
||||||
return status
|
return status
|
||||||
@ -244,23 +244,23 @@ def _get_args(checker):
|
|||||||
def _get_checkers():
|
def _get_checkers():
|
||||||
"""Get a dict of checkers we need to execute."""
|
"""Get a dict of checkers we need to execute."""
|
||||||
# "Static" checkers
|
# "Static" checkers
|
||||||
checkers = OrderedDict([
|
checkers = collections.OrderedDict([
|
||||||
('global', OrderedDict([
|
('global', collections.OrderedDict([
|
||||||
('unittest', check_unittest),
|
('unittest', check_unittest),
|
||||||
('git', check_git),
|
('git', check_git),
|
||||||
])),
|
])),
|
||||||
('setup', OrderedDict([
|
('setup', collections.OrderedDict([
|
||||||
('pyroma', partial(run, 'pyroma')),
|
('pyroma', functools.partial(run, 'pyroma')),
|
||||||
('check-manifest', partial(run, 'check-manifest')),
|
('check-manifest', functools.partial(run, 'check-manifest')),
|
||||||
])),
|
])),
|
||||||
])
|
])
|
||||||
# "Dynamic" checkers which exist once for each target.
|
# "Dynamic" checkers which exist once for each target.
|
||||||
for target in config.get('DEFAULT', 'targets').split(','):
|
for target in config.get('DEFAULT', 'targets').split(','):
|
||||||
checkers[target] = OrderedDict([
|
checkers[target] = collections.OrderedDict([
|
||||||
('pep257', partial(check_pep257, target)),
|
('pep257', functools.partial(check_pep257, target)),
|
||||||
('flake8', partial(run, 'flake8', target)),
|
('flake8', functools.partial(run, 'flake8', target)),
|
||||||
('vcs', partial(check_vcs_conflict, target)),
|
('vcs', functools.partial(check_vcs_conflict, target)),
|
||||||
('pylint', partial(run, 'pylint', target)),
|
('pylint', functools.partial(run, 'pylint', target)),
|
||||||
])
|
])
|
||||||
return checkers
|
return checkers
|
||||||
|
|
||||||
@ -279,7 +279,7 @@ def _checker_enabled(args, group, name):
|
|||||||
def main():
|
def main():
|
||||||
"""Main entry point."""
|
"""Main entry point."""
|
||||||
col.init()
|
col.init()
|
||||||
exit_status = OrderedDict()
|
exit_status = collections.OrderedDict()
|
||||||
exit_status_bool = {}
|
exit_status_bool = {}
|
||||||
parser = argparse.ArgumentParser(description='Run various checkers.')
|
parser = argparse.ArgumentParser(description='Run various checkers.')
|
||||||
parser.add_argument('-s', '--setup', help="Run additional setup checks",
|
parser.add_argument('-s', '--setup', help="Run additional setup checks",
|
||||||
|
@ -23,20 +23,20 @@
|
|||||||
import sys
|
import sys
|
||||||
import cProfile
|
import cProfile
|
||||||
import os.path
|
import os.path
|
||||||
from os import getcwd
|
import os
|
||||||
from tempfile import mkdtemp
|
import tempfile
|
||||||
from subprocess import call
|
import subprocess
|
||||||
from shutil import rmtree
|
import shutil
|
||||||
|
|
||||||
sys.path.insert(0, getcwd())
|
sys.path.insert(0, os.getcwd())
|
||||||
|
|
||||||
import qutebrowser.qutebrowser # pylint: disable=unused-import
|
import qutebrowser.qutebrowser # pylint: disable=unused-import
|
||||||
|
|
||||||
tempdir = mkdtemp()
|
tempdir = tempfile.mkdtemp()
|
||||||
|
|
||||||
if '--profile-keep' in sys.argv:
|
if '--profile-keep' in sys.argv:
|
||||||
sys.argv.remove('--profile-keep')
|
sys.argv.remove('--profile-keep')
|
||||||
profilefile = os.path.join(getcwd(), 'profile')
|
profilefile = os.path.join(os.getcwd(), 'profile')
|
||||||
else:
|
else:
|
||||||
profilefile = os.path.join(tempdir, 'profile')
|
profilefile = os.path.join(tempdir, 'profile')
|
||||||
if '--profile-noconv' in sys.argv:
|
if '--profile-noconv' in sys.argv:
|
||||||
@ -51,5 +51,6 @@ profiler.run('qutebrowser.qutebrowser.main()')
|
|||||||
profiler.dump_stats(profilefile)
|
profiler.dump_stats(profilefile)
|
||||||
|
|
||||||
if not noconv:
|
if not noconv:
|
||||||
call(['pyprof2calltree', '-k', '-i', profilefile, '-o', callgraphfile])
|
subprocess.call(['pyprof2calltree', '-k', '-i', profilefile,
|
||||||
rmtree(tempdir)
|
'-o', callgraphfile])
|
||||||
|
shutil.rmtree(tempdir)
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
|
|
||||||
"""Update 3rd-party files (currently only ez_setup.py)."""
|
"""Update 3rd-party files (currently only ez_setup.py)."""
|
||||||
|
|
||||||
from urllib.request import urlretrieve
|
import urllib.request
|
||||||
|
|
||||||
urlretrieve('https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py',
|
urllib.request.urlretrieve(
|
||||||
'scripts/ez_setup.py')
|
'https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py',
|
||||||
|
'scripts/ez_setup.py')
|
||||||
|
16
setup.py
16
setup.py
@ -24,11 +24,11 @@
|
|||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
from scripts.setupcommon import setupdata, write_git_file
|
from scripts import setupcommon as common
|
||||||
|
|
||||||
from scripts.ez_setup import use_setuptools
|
from scripts import ez_setup
|
||||||
use_setuptools()
|
ez_setup.use_setuptools()
|
||||||
from setuptools import setup, find_packages
|
import setuptools
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -38,9 +38,9 @@ except NameError:
|
|||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
write_git_file()
|
common.write_git_file()
|
||||||
setup(
|
setuptools.setup(
|
||||||
packages=find_packages(exclude=['qutebrowser.test']),
|
packages=setuptools.find_packages(exclude=['qutebrowser.test']),
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
package_data={'qutebrowser': ['html/*', 'git-commit-id']},
|
package_data={'qutebrowser': ['html/*', 'git-commit-id']},
|
||||||
entry_points={'gui_scripts':
|
entry_points={'gui_scripts':
|
||||||
@ -51,7 +51,7 @@ try:
|
|||||||
extras_require={'nice-debugging': ['colorlog', 'colorama'],
|
extras_require={'nice-debugging': ['colorlog', 'colorama'],
|
||||||
'checks': ['flake8', 'pylint', 'check-manifest',
|
'checks': ['flake8', 'pylint', 'check-manifest',
|
||||||
'pyroma']},
|
'pyroma']},
|
||||||
**setupdata
|
**common.setupdata
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
if BASEDIR is not None:
|
if BASEDIR is not None:
|
||||||
|
Loading…
Reference in New Issue
Block a user