From fe05947b54be138ef261da00eda01474fc690345 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 17 Sep 2017 22:47:46 +0200 Subject: [PATCH] Add a new qt_args setting See #2589 --- doc/help/settings.asciidoc | 10 +++++++ qutebrowser/app.py | 2 +- qutebrowser/config/config.py | 23 ++++++++++++++ qutebrowser/config/configdata.yml | 13 ++++++++ qutebrowser/utils/qtutils.py | 22 -------------- tests/unit/config/test_config.py | 50 +++++++++++++++++++++++++++++++ tests/unit/utils/test_qtutils.py | 46 ---------------------------- 7 files changed, 97 insertions(+), 69 deletions(-) diff --git a/doc/help/settings.asciidoc b/doc/help/settings.asciidoc index 236184126..b0d5707fb 100644 --- a/doc/help/settings.asciidoc +++ b/doc/help/settings.asciidoc @@ -208,6 +208,7 @@ |<>|Which window to choose when opening links as new tabs. |<>|Show a filebrowser in upload/download prompts. |<>|The rounding radius for the edges of prompts. +|<>|Additional arguments to pass to Qt, without leading `--`. |<>|Show a scrollbar. |<>|Enable smooth scrolling for web pages. |<>|The name of the session to save by default. @@ -2604,6 +2605,15 @@ Type: <> Default: +pass:[8]+ +[[qt_args]] +=== qt_args +Additional arguments to pass to Qt, without leading `--`. +With QtWebEngine, some Chromium arguments (see https://peter.sh/experiments/chromium-command-line-switches/ for a list) will work. + +Type: <> + +Default: empty + [[scrolling.bar]] === scrolling.bar Show a scrollbar. diff --git a/qutebrowser/app.py b/qutebrowser/app.py index f8cf49723..257e15b0d 100644 --- a/qutebrowser/app.py +++ b/qutebrowser/app.py @@ -770,7 +770,7 @@ class Application(QApplication): """ self._last_focus_object = None - qt_args = qtutils.get_args(args) + qt_args = config.qt_args(args) log.init.debug("Qt arguments: {}, based on {}".format(qt_args, args)) super().__init__(qt_args) diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py index 3047b79b7..4ccadfefb 100644 --- a/qutebrowser/config/config.py +++ b/qutebrowser/config/config.py @@ -19,6 +19,7 @@ """Configuration storage and config-related utilities.""" +import sys import copy import contextlib import functools @@ -704,3 +705,25 @@ def late_init(save_manager): instance.init_save_manager(save_manager) configfiles.state.init_save_manager(save_manager) + + +def qt_args(namespace): + """Get the Qt QApplication arguments based on an argparse namespace. + + Args: + namespace: The argparse namespace. + + Return: + The argv list to be passed to Qt. + """ + argv = [sys.argv[0]] + + if namespace.qt_flag is not None: + argv += ['--' + flag[0] for flag in namespace.qt_flag] + + if namespace.qt_arg is not None: + for name, value in namespace.qt_arg: + argv += ['--' + name, value] + + argv += ['--' + arg for arg in val.qt_args] + return argv diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 13941de03..516eeaccf 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -85,6 +85,19 @@ session_default_name: If this is set to null, the session which was last loaded is saved. +qt_args: + type: + name: List + valtype: String + none_ok: true + default: [] + desc: >- + Additional arguments to pass to Qt, without leading `--`. + + With QtWebEngine, some Chromium arguments (see + https://peter.sh/experiments/chromium-command-line-switches/ for a list) + will work. + ## auto_save auto_save.interval: diff --git a/qutebrowser/utils/qtutils.py b/qutebrowser/utils/qtutils.py index ad02c9a45..6a3a5e972 100644 --- a/qutebrowser/utils/qtutils.py +++ b/qutebrowser/utils/qtutils.py @@ -29,7 +29,6 @@ Module attributes: import io import os -import sys import operator import contextlib @@ -138,27 +137,6 @@ def check_overflow(arg, ctype, fatal=True): return arg -def get_args(namespace): - """Get the Qt QApplication arguments based on an argparse namespace. - - Args: - namespace: The argparse namespace. - - Return: - The argv list to be passed to Qt. - """ - argv = [sys.argv[0]] - - if namespace.qt_flag is not None: - argv += ['--' + flag[0] for flag in namespace.qt_flag] - - if namespace.qt_arg is not None: - for name, value in namespace.qt_arg: - argv += ['--' + name, value] - - return argv - - def check_print_compat(): """Check if printing should work in the given Qt version.""" # WORKAROUND (remove this when we bump the requirements to 5.3.0) diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py index 64d36082f..3a151a939 100644 --- a/tests/unit/config/test_config.py +++ b/tests/unit/config/test_config.py @@ -18,6 +18,7 @@ """Tests for qutebrowser.config.config.""" +import sys import copy import types import logging @@ -27,6 +28,7 @@ import pytest from PyQt5.QtCore import QObject, QUrl from PyQt5.QtGui import QColor +from qutebrowser import qutebrowser from qutebrowser.commands import cmdexc from qutebrowser.config import config, configdata, configexc, configfiles from qutebrowser.utils import objreg, usertypes @@ -982,3 +984,51 @@ def test_late_init(init_patch, monkeypatch, fake_save_manager, mocker, errors): assert 'Error text: Exception' in text else: assert not msgbox_mock.called + + +class TestQtArgs: + + @pytest.fixture + def parser(self, mocker): + """Fixture to provide an argparser. + + Monkey-patches .exit() of the argparser so it doesn't exit on errors. + """ + parser = qutebrowser.get_argparser() + mocker.patch.object(parser, 'exit', side_effect=Exception) + return parser + + @pytest.mark.parametrize('args, expected', [ + # No Qt arguments + (['--debug'], [sys.argv[0]]), + # Qt flag + (['--debug', '--qt-flag', 'reverse'], [sys.argv[0], '--reverse']), + # Qt argument with value + (['--qt-arg', 'stylesheet', 'foo'], + [sys.argv[0], '--stylesheet', 'foo']), + # --qt-arg given twice + (['--qt-arg', 'stylesheet', 'foo', '--qt-arg', 'geometry', 'bar'], + [sys.argv[0], '--stylesheet', 'foo', '--geometry', 'bar']), + # --qt-flag given twice + (['--qt-flag', 'foo', '--qt-flag', 'bar'], + [sys.argv[0], '--foo', '--bar']), + ]) + def test_qt_args(self, config_stub, args, expected, parser): + """Test commandline with no Qt arguments given.""" + parsed = parser.parse_args(args) + assert config.qt_args(parsed) == expected + + def test_qt_both(self, config_stub, parser): + """Test commandline with a Qt argument and flag.""" + args = parser.parse_args(['--qt-arg', 'stylesheet', 'foobar', + '--qt-flag', 'reverse']) + qt_args = config.qt_args(args) + assert qt_args[0] == sys.argv[0] + assert '--reverse' in qt_args + assert '--stylesheet' in qt_args + assert 'foobar' in qt_args + + def test_with_settings(self, config_stub, parser): + parsed = parser.parse_args(['--qt-flag', 'foo']) + config_stub.val.qt_args = ['bar'] + assert config.qt_args(parsed) == [sys.argv[0], '--foo', '--bar'] diff --git a/tests/unit/utils/test_qtutils.py b/tests/unit/utils/test_qtutils.py index a87b9c745..f0fda7a2e 100644 --- a/tests/unit/utils/test_qtutils.py +++ b/tests/unit/utils/test_qtutils.py @@ -36,7 +36,6 @@ import pytest from PyQt5.QtCore import (QDataStream, QPoint, QUrl, QByteArray, QIODevice, QTimer, QBuffer, QFile, QProcess, QFileDevice) -from qutebrowser import qutebrowser from qutebrowser.utils import qtutils import overflow_test_cases @@ -119,51 +118,6 @@ class TestCheckOverflow: assert newval == repl -class TestGetQtArgs: - - """Tests for get_args.""" - - @pytest.fixture - def parser(self, mocker): - """Fixture to provide an argparser. - - Monkey-patches .exit() of the argparser so it doesn't exit on errors. - """ - parser = qutebrowser.get_argparser() - mocker.patch.object(parser, 'exit', side_effect=Exception) - return parser - - @pytest.mark.parametrize('args, expected', [ - # No Qt arguments - (['--debug'], [sys.argv[0]]), - # Qt flag - (['--debug', '--qt-flag', 'reverse'], [sys.argv[0], '--reverse']), - # Qt argument with value - (['--qt-arg', 'stylesheet', 'foo'], - [sys.argv[0], '--stylesheet', 'foo']), - # --qt-arg given twice - (['--qt-arg', 'stylesheet', 'foo', '--qt-arg', 'geometry', 'bar'], - [sys.argv[0], '--stylesheet', 'foo', '--geometry', 'bar']), - # --qt-flag given twice - (['--qt-flag', 'foo', '--qt-flag', 'bar'], - [sys.argv[0], '--foo', '--bar']), - ]) - def test_qt_args(self, args, expected, parser): - """Test commandline with no Qt arguments given.""" - parsed = parser.parse_args(args) - assert qtutils.get_args(parsed) == expected - - def test_qt_both(self, parser): - """Test commandline with a Qt argument and flag.""" - args = parser.parse_args(['--qt-arg', 'stylesheet', 'foobar', - '--qt-flag', 'reverse']) - qt_args = qtutils.get_args(args) - assert qt_args[0] == sys.argv[0] - assert '--reverse' in qt_args - assert '--stylesheet' in qt_args - assert 'foobar' in qt_args - - @pytest.mark.parametrize('os_name, qversion, expected', [ ('linux', '5.2.1', True), # unaffected OS ('linux', '5.4.1', True), # unaffected OS