From 6e166d139a81b53cbb50a8370d59f7269c3a10cb Mon Sep 17 00:00:00 2001 From: Marius Date: Tue, 20 Jun 2017 21:18:13 +0200 Subject: [PATCH 01/25] Fix alignment of scroll buttons in tab bar --- qutebrowser/mainwindow/tabwidget.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index 2c4eb6eab..9168a28b6 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -759,6 +759,12 @@ class TabBarStyle(QCommonStyle): # style differences... rct = super().subElementRect(sr, opt, widget) return rct + elif sr == QStyle.SE_TabBarScrollLeftButton: + # We need this so the left scroll button is aligned properly. + # Otherwise, empty space will be shown after the last tab even + # though the button width is set to 0 + rct = super().subElementRect(sr, opt, widget) + return rct else: return self._style.subElementRect(sr, opt, widget) From dfedddf0bdb0d803cd8b2d32d74977228c9d58da Mon Sep 17 00:00:00 2001 From: Marius Date: Tue, 20 Jun 2017 23:55:11 +0200 Subject: [PATCH 02/25] Wrap scroll button workaround in try/except for older pyqt5 versions (5.2.1) --- qutebrowser/mainwindow/tabwidget.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index 9168a28b6..2096bf8e0 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -747,6 +747,8 @@ class TabBarStyle(QCommonStyle): Return: A QRect. """ + + if sr == QStyle.SE_TabBarTabText: layouts = self._tab_layout(opt) if layouts is None: @@ -759,13 +761,20 @@ class TabBarStyle(QCommonStyle): # style differences... rct = super().subElementRect(sr, opt, widget) return rct - elif sr == QStyle.SE_TabBarScrollLeftButton: - # We need this so the left scroll button is aligned properly. - # Otherwise, empty space will be shown after the last tab even - # though the button width is set to 0 - rct = super().subElementRect(sr, opt, widget) - return rct else: + try: + # We need this so the left scroll button is aligned properly. + # Otherwise, empty space will be shown after the last tab even + # though the button width is set to 0 + + # In older PyQt-versions (5.2.1) QStyle does not have this + # attribute. + if sr == QStyle.SE_TabBarScrollLeftButton: + return super().subElementRect(sr, opt, widget) + + except AttributeError: + pass + return self._style.subElementRect(sr, opt, widget) def _tab_layout(self, opt): From f3a2b84033f0f25a298386e705839271df317157 Mon Sep 17 00:00:00 2001 From: Marius Date: Tue, 20 Jun 2017 23:58:23 +0200 Subject: [PATCH 03/25] remove space --- qutebrowser/mainwindow/tabwidget.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index 2096bf8e0..84cec79c8 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -747,8 +747,6 @@ class TabBarStyle(QCommonStyle): Return: A QRect. """ - - if sr == QStyle.SE_TabBarTabText: layouts = self._tab_layout(opt) if layouts is None: From df6b8b7ff52d5fb5aedf911c03f319c85a1f54b9 Mon Sep 17 00:00:00 2001 From: Marius Date: Wed, 21 Jun 2017 09:03:15 +0200 Subject: [PATCH 04/25] Update tabwidget.py --- qutebrowser/mainwindow/tabwidget.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index 84cec79c8..3dd0d28da 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -764,8 +764,8 @@ class TabBarStyle(QCommonStyle): # We need this so the left scroll button is aligned properly. # Otherwise, empty space will be shown after the last tab even # though the button width is set to 0 - - # In older PyQt-versions (5.2.1) QStyle does not have this + # + # In older PyQt-versions (5.2.1) QStyle does not have this # attribute. if sr == QStyle.SE_TabBarScrollLeftButton: return super().subElementRect(sr, opt, widget) From 7eacea1057c78e1f29c0ea6934e5fbecbf92c297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= Date: Tue, 4 Jul 2017 14:12:21 +0200 Subject: [PATCH 05/25] Preserve fullscreen when exiting video fullscreen Fixes #2778 --- qutebrowser/browser/webengine/webenginetab.py | 1 + qutebrowser/mainwindow/mainwindow.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 0a4c2dfc7..494ba840c 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -615,6 +615,7 @@ class WebEngineTab(browsertab.AbstractTab): def shutdown(self): self.shutting_down.emit() + self.action.exit_fullscreen() if qtutils.version_check('5.8', exact=True): # WORKAROUND for # https://bugreports.qt.io/browse/QTBUG-58563 diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 067b536bf..5ea212b18 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -128,6 +128,8 @@ class MainWindow(QWidget): _commandrunner: The main CommandRunner instance. _overlays: Widgets shown as overlay for the current webpage. _private: Whether the window is in private browsing mode. + _restore_fullscreen: Whether to restore the fullscreen after leaving + a video fullscreen. """ def __init__(self, *, private, geometry=None, parent=None): @@ -217,6 +219,8 @@ class MainWindow(QWidget): objreg.get("app").new_window.emit(self) + self._restore_fullscreen = False + def _init_geometry(self, geometry): """Initialize the window geometry or load it from disk.""" if geometry is not None: @@ -483,9 +487,14 @@ class MainWindow(QWidget): @pyqtSlot(bool) def _on_fullscreen_requested(self, on): if on: + self._restore_fullscreen = self.isFullScreen() self.showFullScreen() - else: + elif not self._restore_fullscreen: self.showNormal() + else: + self._restore_fullscreen = self.isFullScreen() + log.misc.debug('on: {}, restore fullscreen: {}' + .format(on, self._restore_fullscreen)) @cmdutils.register(instance='main-window', scope='window') @pyqtSlot() From 7ea7a2f3fd029fc58e78965151974262de2d567a Mon Sep 17 00:00:00 2001 From: Christian Helbling Date: Tue, 4 Jul 2017 17:50:07 +0200 Subject: [PATCH 06/25] restore maximized state on :fullscreen and when exiting video fullscreen --- qutebrowser/browser/commands.py | 6 +++++- qutebrowser/mainwindow/mainwindow.py | 13 ++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 3d8516fe2..e3b7398ed 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -2171,6 +2171,10 @@ class CommandDispatcher: window = self._tabbed_browser.window() if window.isFullScreen(): - window.showNormal() + if window._restore_maximized: + window.showMaximized() + else: + window.showNormal() else: + window._restore_maximized = window.isMaximized() window.showFullScreen() diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 5ea212b18..d8fe052b1 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -130,6 +130,8 @@ class MainWindow(QWidget): _private: Whether the window is in private browsing mode. _restore_fullscreen: Whether to restore the fullscreen after leaving a video fullscreen. + _restore_maximized: Whether to restore maximized window after leaving + a video fullscreen. """ def __init__(self, *, private, geometry=None, parent=None): @@ -220,6 +222,7 @@ class MainWindow(QWidget): objreg.get("app").new_window.emit(self) self._restore_fullscreen = False + self._restore_maximized = self.isMaximized() def _init_geometry(self, geometry): """Initialize the window geometry or load it from disk.""" @@ -488,13 +491,17 @@ class MainWindow(QWidget): def _on_fullscreen_requested(self, on): if on: self._restore_fullscreen = self.isFullScreen() + self._restore_maximized = self.isMaximized() self.showFullScreen() elif not self._restore_fullscreen: - self.showNormal() + if self._restore_maximized: + self.showMaximized() + else: + self.showNormal() else: self._restore_fullscreen = self.isFullScreen() - log.misc.debug('on: {}, restore fullscreen: {}' - .format(on, self._restore_fullscreen)) + log.misc.debug('on: {}, restore fullscreen: {}, restore maximized: {}' + .format(on, self._restore_fullscreen, self._restore_maximized)) @cmdutils.register(instance='main-window', scope='window') @pyqtSlot() From 20db65e430beb7bbe9f6f0b895dcaea34c64cd55 Mon Sep 17 00:00:00 2001 From: Christian Helbling Date: Tue, 4 Jul 2017 22:56:44 +0200 Subject: [PATCH 07/25] preserve window state when exiting video fullscreen --- qutebrowser/browser/commands.py | 7 ++----- qutebrowser/mainwindow/mainwindow.py | 22 ++++++---------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index e3b7398ed..080c3e209 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -2171,10 +2171,7 @@ class CommandDispatcher: window = self._tabbed_browser.window() if window.isFullScreen(): - if window._restore_maximized: - window.showMaximized() - else: - window.showNormal() + window.setWindowState(window._state_before_fullscreen & ~Qt.WindowFullScreen) else: - window._restore_maximized = window.isMaximized() + window._state_before_fullscreen = window.windowState() window.showFullScreen() diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index d8fe052b1..2fac3f51a 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -128,10 +128,7 @@ class MainWindow(QWidget): _commandrunner: The main CommandRunner instance. _overlays: Widgets shown as overlay for the current webpage. _private: Whether the window is in private browsing mode. - _restore_fullscreen: Whether to restore the fullscreen after leaving - a video fullscreen. - _restore_maximized: Whether to restore maximized window after leaving - a video fullscreen. + _state_before_fullscreen: window state before activation of fullscreen """ def __init__(self, *, private, geometry=None, parent=None): @@ -221,8 +218,7 @@ class MainWindow(QWidget): objreg.get("app").new_window.emit(self) - self._restore_fullscreen = False - self._restore_maximized = self.isMaximized() + self._state_before_fullscreen = self.windowState() def _init_geometry(self, geometry): """Initialize the window geometry or load it from disk.""" @@ -490,18 +486,12 @@ class MainWindow(QWidget): @pyqtSlot(bool) def _on_fullscreen_requested(self, on): if on: - self._restore_fullscreen = self.isFullScreen() - self._restore_maximized = self.isMaximized() + self._state_before_fullscreen = self.windowState() self.showFullScreen() - elif not self._restore_fullscreen: - if self._restore_maximized: - self.showMaximized() - else: - self.showNormal() else: - self._restore_fullscreen = self.isFullScreen() - log.misc.debug('on: {}, restore fullscreen: {}, restore maximized: {}' - .format(on, self._restore_fullscreen, self._restore_maximized)) + self.setWindowState(self._state_before_fullscreen) + log.misc.debug('on: {}, state before fullscreen: {}' + .format(on, self._state_before_fullscreen)) @cmdutils.register(instance='main-window', scope='window') @pyqtSlot() From 361251bf538c61239b8c007b5643ba993dc2e0b9 Mon Sep 17 00:00:00 2001 From: Christian Helbling Date: Tue, 4 Jul 2017 23:30:06 +0200 Subject: [PATCH 08/25] mark public attribute as public, fix debug output --- qutebrowser/browser/commands.py | 8 +++++--- qutebrowser/mainwindow/mainwindow.py | 14 +++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 080c3e209..9f7cef9d4 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -38,7 +38,7 @@ from qutebrowser.browser import (urlmarks, browsertab, inspector, navigate, webelem, downloads) from qutebrowser.keyinput import modeman from qutebrowser.utils import (message, usertypes, log, qtutils, urlutils, - objreg, utils, typing) + objreg, utils, typing, debug) from qutebrowser.utils.usertypes import KeyMode from qutebrowser.misc import editor, guiprocess from qutebrowser.completion.models import instances, sortfilter @@ -2171,7 +2171,9 @@ class CommandDispatcher: window = self._tabbed_browser.window() if window.isFullScreen(): - window.setWindowState(window._state_before_fullscreen & ~Qt.WindowFullScreen) + window.setWindowState(window.state_before_fullscreen & ~Qt.WindowFullScreen) else: - window._state_before_fullscreen = window.windowState() + window.state_before_fullscreen = window.windowState() window.showFullScreen() + log.misc.debug('state before fullscreen: {}' + .format(debug.qflags_key(Qt, window.state_before_fullscreen))) diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 2fac3f51a..6edabda09 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -30,7 +30,7 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication, QSizePolicy from qutebrowser.commands import runners, cmdutils from qutebrowser.config import config -from qutebrowser.utils import message, log, usertypes, qtutils, objreg, utils +from qutebrowser.utils import message, log, usertypes, qtutils, objreg, utils, debug from qutebrowser.mainwindow import tabbedbrowser, messageview, prompt from qutebrowser.mainwindow.statusbar import bar from qutebrowser.completion import completionwidget, completer @@ -123,12 +123,12 @@ class MainWindow(QWidget): Attributes: status: The StatusBar widget. tabbed_browser: The TabbedBrowser widget. + state_before_fullscreen: window state before activation of fullscreen. _downloadview: The DownloadView widget. _vbox: The main QVBoxLayout. _commandrunner: The main CommandRunner instance. _overlays: Widgets shown as overlay for the current webpage. _private: Whether the window is in private browsing mode. - _state_before_fullscreen: window state before activation of fullscreen """ def __init__(self, *, private, geometry=None, parent=None): @@ -218,7 +218,7 @@ class MainWindow(QWidget): objreg.get("app").new_window.emit(self) - self._state_before_fullscreen = self.windowState() + self.state_before_fullscreen = self.windowState() def _init_geometry(self, geometry): """Initialize the window geometry or load it from disk.""" @@ -486,12 +486,12 @@ class MainWindow(QWidget): @pyqtSlot(bool) def _on_fullscreen_requested(self, on): if on: - self._state_before_fullscreen = self.windowState() + self.state_before_fullscreen = self.windowState() self.showFullScreen() else: - self.setWindowState(self._state_before_fullscreen) - log.misc.debug('on: {}, state before fullscreen: {}' - .format(on, self._state_before_fullscreen)) + self.setWindowState(self.state_before_fullscreen) + log.misc.debug('on: {}, state before fullscreen: {}'.format( + on, debug.qflags_key(Qt, self.state_before_fullscreen))) @cmdutils.register(instance='main-window', scope='window') @pyqtSlot() From f15dbecc73b33df46b314232740d604520fa46c9 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 5 Jul 2017 21:49:34 +0200 Subject: [PATCH 09/25] Update changelog for unreleased versions --- CHANGELOG.asciidoc | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 14fd41b88..bd7c8d2f7 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -14,6 +14,34 @@ This project adheres to http://semver.org/[Semantic Versioning]. // `Fixed` for any bug fixes. // `Security` to invite users to upgrade in case of vulnerabilities. +v0.1.0 (unreleased) +------------------- + +Breaking changes +~~~~~~~~~~~~~~~~ + +- Support for legacy QtWebKit (before 5.212 which is distributed + independently from Qt) is dropped. +- Support for Python 3.4 is dropped. +- Support for Qt before 5.7 is dropped. +- New dependency on the QtSql module and Qt sqlite support. +- New dependency on ruamel.yaml; dropped PyYAML dependency. +- The QtWebEngine backend is now used by default if available. +- New config system which ignores the old config file. + +Major changes +~~~~~~~~~~~~~ + +- New completion engine based on sqlite, which allows to complete + the entire browsing history. +- Completely rewritten configuration system. + +v0.11.1 (unreleased) +-------------------- + +Fixes +~~~~~ + v0.11.0 ------- From a8120a23c4b24c203e07a8ca80105aa22c607e63 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 5 Jul 2017 22:13:24 +0200 Subject: [PATCH 10/25] Update comment for TabBarStyle --- qutebrowser/mainwindow/tabwidget.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index 3dd0d28da..d1beea7c7 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -765,11 +765,9 @@ class TabBarStyle(QCommonStyle): # Otherwise, empty space will be shown after the last tab even # though the button width is set to 0 # - # In older PyQt-versions (5.2.1) QStyle does not have this - # attribute. + # QStyle.SE_TabBarScrollLeftButton was added in Qt 5.7 if sr == QStyle.SE_TabBarScrollLeftButton: return super().subElementRect(sr, opt, widget) - except AttributeError: pass From 0304040cbbf53043573a1b1104f4f0e9efd5ba02 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 5 Jul 2017 22:14:01 +0200 Subject: [PATCH 11/25] Update docs --- README.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.asciidoc b/README.asciidoc index daa008a83..98e13a538 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -193,6 +193,7 @@ Contributors, sorted by the number of commits in descending order: * knaggita * Oliver Caldwell * Nikolay Amiantov +* Marius * Julian Weigt * Tomasz Kramkowski * Sebastian Frysztak @@ -217,7 +218,6 @@ Contributors, sorted by the number of commits in descending order: * Michał Góral * Michael Ilsaas * Martin Zimmermann -* Marius * Link * Jussi Timperi * Cosmin Popescu From 6b4e0ad2bcd8d179baf8c2961651bdc469b3fae5 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 5 Jul 2017 22:14:49 +0200 Subject: [PATCH 12/25] Update changelog --- CHANGELOG.asciidoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index bd7c8d2f7..15e087c6b 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -42,6 +42,8 @@ v0.11.1 (unreleased) Fixes ~~~~~ +- Fixed empty space being shown after tabs in the tabbar in some cases. + v0.11.0 ------- From 3c9de92d5857b3cd26633cfd18c976678c07f789 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 6 Jul 2017 00:40:58 +0200 Subject: [PATCH 13/25] Add Gentoo instructions to backend warning --- qutebrowser/html/backend-warning.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qutebrowser/html/backend-warning.html b/qutebrowser/html/backend-warning.html index ffff0e59b..2b631d6a5 100644 --- a/qutebrowser/html/backend-warning.html +++ b/qutebrowser/html/backend-warning.html @@ -70,6 +70,8 @@ the qute://settings page or caret browsing). {{ install_webengine('qt5-qtwebengine') }} {% elif distribution.parsed == Distribution.opensuse %} {{ install_webengine('libqt5-qtwebengine') }} +{% elif distribution.parsed == Distribution.gentoo %} + {{ install_webengine('dev-qt/qtwebengine') }} {% else %} {{ unknown_system() }} {% endif %} From 94951d92a18f9535919398c703f41c982d201f4c Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 6 Jul 2017 12:15:42 +0200 Subject: [PATCH 14/25] Simplify arg handling in test_version_output --- tests/unit/utils/test_version.py | 50 +++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index 32c3fcf5c..dae823ba9 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -799,18 +799,27 @@ def test_chromium_version_unpatched(qapp): assert version._chromium_version() not in ['', 'unknown', 'unavailable'] -@pytest.mark.parametrize(['git_commit', 'frozen', 'style', 'with_webkit', - 'known_distribution'], [ - (True, False, True, True, True), # normal - (False, False, True, True, True), # no git commit - (True, True, True, True, True), # frozen - (True, True, False, True, True), # no style - (True, False, True, False, True), # no webkit - (True, False, True, 'ng', True), # QtWebKit-NG - (True, False, True, True, False), # unknown Linux distribution +class VersionParams: + + def __init__(self, git_commit=True, frozen=False, style=True, + with_webkit=True, known_distribution=True): + self.git_commit = git_commit + self.frozen = frozen + self.style = style + self.with_webkit = with_webkit + self.known_distribution = known_distribution + + +@pytest.mark.parametrize('params', [ + VersionParams(), + VersionParams(git_commit=False), + VersionParams(frozen=True), + VersionParams(style=False), + VersionParams(with_webkit=False), + VersionParams(with_webkit='ng'), + VersionParams(known_distribution=False), ]) # pylint: disable=too-many-locals -def test_version_output(git_commit, frozen, style, with_webkit, - known_distribution, stubs, monkeypatch): +def test_version_output(params, stubs, monkeypatch): """Test version.version().""" class FakeWebEngineProfile: def httpUserAgent(self): @@ -820,7 +829,7 @@ def test_version_output(git_commit, frozen, style, with_webkit, patches = { 'qutebrowser.__file__': os.path.join(import_path, '__init__.py'), 'qutebrowser.__version__': 'VERSION', - '_git_str': lambda: ('GIT COMMIT' if git_commit else None), + '_git_str': lambda: ('GIT COMMIT' if params.git_commit else None), 'platform.python_implementation': lambda: 'PYTHON IMPLEMENTATION', 'platform.python_version': lambda: 'PYTHON VERSION', 'PYQT_VERSION_STR': 'PYQT VERSION', @@ -832,24 +841,25 @@ def test_version_output(git_commit, frozen, style, with_webkit, 'platform.architecture': lambda: ('ARCHITECTURE', ''), '_os_info': lambda: ['OS INFO 1', 'OS INFO 2'], '_path_info': lambda: {'PATH DESC': 'PATH NAME'}, - 'QApplication': (stubs.FakeQApplication(style='STYLE') if style else + 'QApplication': (stubs.FakeQApplication(style='STYLE') + if params.style else stubs.FakeQApplication(instance=None)), 'QLibraryInfo.location': (lambda _loc: 'QT PATH'), } substitutions = { - 'git_commit': '\nGit commit: GIT COMMIT' if git_commit else '', - 'style': '\nStyle: STYLE' if style else '', + 'git_commit': '\nGit commit: GIT COMMIT' if params.git_commit else '', + 'style': '\nStyle: STYLE' if params.style else '', 'qt': 'QT VERSION', - 'frozen': str(frozen), + 'frozen': str(params.frozen), 'import_path': import_path, } - if with_webkit: + if params.with_webkit: patches['qWebKitVersion'] = lambda: 'WEBKIT VERSION' patches['objects.backend'] = usertypes.Backend.QtWebKit patches['QWebEngineProfile'] = None - if with_webkit == 'ng': + if params.with_webkit == 'ng': backend = 'QtWebKit-NG' patches['qtutils.is_qtwebkit_ng'] = lambda: True else: @@ -862,7 +872,7 @@ def test_version_output(git_commit, frozen, style, with_webkit, patches['QWebEngineProfile'] = FakeWebEngineProfile substitutions['backend'] = 'QtWebEngine (Chromium CHROMIUMVERSION)' - if known_distribution: + if params.known_distribution: patches['distribution'] = lambda: version.DistributionInfo( parsed=version.Distribution.arch, version=None, pretty='LINUX DISTRIBUTION', id='arch') @@ -877,7 +887,7 @@ def test_version_output(git_commit, frozen, style, with_webkit, for attr, val in patches.items(): monkeypatch.setattr('qutebrowser.utils.version.' + attr, val) - if frozen: + if params.frozen: monkeypatch.setattr(sys, 'frozen', True, raising=False) else: monkeypatch.delattr(sys, 'frozen', raising=False) From 911e59b0f49cbc1594dfaf608ff93f6acd2ca6a4 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 6 Jul 2017 12:23:08 +0200 Subject: [PATCH 15/25] Improve version output without SSL support --- qutebrowser/utils/version.py | 7 +++---- tests/unit/utils/test_version.py | 16 +++++++++++----- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/qutebrowser/utils/version.py b/qutebrowser/utils/version.py index e1cc26e64..dd36f381c 100644 --- a/qutebrowser/utils/version.py +++ b/qutebrowser/utils/version.py @@ -326,11 +326,10 @@ def version(): lines += _module_versions() - lines += ['pdf.js: {}'.format(_pdfjs_version())] - lines += [ - 'SSL: {}'.format(QSslSocket.sslLibraryVersionString()), - '', + 'pdf.js: {}'.format(_pdfjs_version()), + 'QtNetwork SSL: {}\n'.format(QSslSocket.sslLibraryVersionString() + if QSslSocket.supportsSsl() else 'no'), ] qapp = QApplication.instance() diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index dae823ba9..aede735d4 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -759,14 +759,16 @@ class FakeQSslSocket: Attributes: _version: What QSslSocket::sslLibraryVersionString() should return. + _support: Whether SSL is supported. """ - def __init__(self, version=None): + def __init__(self, version=None, support=True): self._version = version + self._support = support def supportsSsl(self): """Fake for QSslSocket::supportsSsl().""" - return True + return self._support def sslLibraryVersionString(self): """Fake for QSslSocket::sslLibraryVersionString().""" @@ -802,12 +804,13 @@ def test_chromium_version_unpatched(qapp): class VersionParams: def __init__(self, git_commit=True, frozen=False, style=True, - with_webkit=True, known_distribution=True): + with_webkit=True, known_distribution=True, ssl_support=True): self.git_commit = git_commit self.frozen = frozen self.style = style self.with_webkit = with_webkit self.known_distribution = known_distribution + self.ssl_support = ssl_support @pytest.mark.parametrize('params', [ @@ -818,6 +821,7 @@ class VersionParams: VersionParams(with_webkit=False), VersionParams(with_webkit='ng'), VersionParams(known_distribution=False), + VersionParams(ssl_support=False), ]) # pylint: disable=too-many-locals def test_version_output(params, stubs, monkeypatch): """Test version.version().""" @@ -836,7 +840,7 @@ def test_version_output(params, stubs, monkeypatch): 'earlyinit.qt_version': lambda: 'QT VERSION', '_module_versions': lambda: ['MODULE VERSION 1', 'MODULE VERSION 2'], '_pdfjs_version': lambda: 'PDFJS VERSION', - 'QSslSocket': FakeQSslSocket('SSL VERSION'), + 'QSslSocket': FakeQSslSocket('SSL VERSION', params.ssl_support), 'platform.platform': lambda: 'PLATFORM', 'platform.architecture': lambda: ('ARCHITECTURE', ''), '_os_info': lambda: ['OS INFO 1', 'OS INFO 2'], @@ -884,6 +888,8 @@ def test_version_output(params, stubs, monkeypatch): substitutions['linuxdist'] = '' substitutions['osinfo'] = 'OS INFO 1\nOS INFO 2\n' + substitutions['ssl'] = 'SSL VERSION' if params.ssl_support else 'no' + for attr, val in patches.items(): monkeypatch.setattr('qutebrowser.utils.version.' + attr, val) @@ -903,7 +909,7 @@ def test_version_output(params, stubs, monkeypatch): MODULE VERSION 1 MODULE VERSION 2 pdf.js: PDFJS VERSION - SSL: SSL VERSION + QtNetwork SSL: {ssl} {style} Platform: PLATFORM, ARCHITECTURE{linuxdist} Frozen: {frozen} From 66168a5b49e224df019d65e3a51b3dda9b1aede3 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 6 Jul 2017 12:25:11 +0200 Subject: [PATCH 16/25] Add test ids to test_version_output --- tests/unit/utils/test_version.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index aede735d4..c60150143 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -803,8 +803,9 @@ def test_chromium_version_unpatched(qapp): class VersionParams: - def __init__(self, git_commit=True, frozen=False, style=True, + def __init__(self, name, git_commit=True, frozen=False, style=True, with_webkit=True, known_distribution=True, ssl_support=True): + self.name = name self.git_commit = git_commit self.frozen = frozen self.style = style @@ -814,15 +815,15 @@ class VersionParams: @pytest.mark.parametrize('params', [ - VersionParams(), - VersionParams(git_commit=False), - VersionParams(frozen=True), - VersionParams(style=False), - VersionParams(with_webkit=False), - VersionParams(with_webkit='ng'), - VersionParams(known_distribution=False), - VersionParams(ssl_support=False), -]) # pylint: disable=too-many-locals + VersionParams('normal'), + VersionParams('no-git-commit', git_commit=False), + VersionParams('frozen', frozen=True), + VersionParams('no-style', style=False), + VersionParams('no-webkit', with_webkit=False), + VersionParams('webkit-ng', with_webkit='ng'), + VersionParams('unknown-dist', known_distribution=False), + VersionParams('no-ssl', ssl_support=False), +], ids=lambda param: param.name) # pylint: disable=too-many-locals def test_version_output(params, stubs, monkeypatch): """Test version.version().""" class FakeWebEngineProfile: From 338d62204e11558976530a3003ff74c533601904 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 6 Jul 2017 12:36:11 +0200 Subject: [PATCH 17/25] Make TestModuleVersions in test_version more maintainable --- tests/unit/utils/test_version.py | 87 ++++++++++++++++---------------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index c60150143..5623d0ce3 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -21,6 +21,7 @@ import io import sys +import collections import os.path import subprocess import contextlib @@ -475,29 +476,32 @@ class ImportFake: """A fake for __import__ which is used by the import_fake fixture. Attributes: - exists: A dict mapping module names to bools. If True, the import will - success. Otherwise, it'll fail with ImportError. + modules: A dict mapping module names to bools. If True, the import will + success. Otherwise, it'll fail with ImportError. version_attribute: The name to use in the fake modules for the version attribute. version: The version to use for the modules. _real_import: Saving the real __import__ builtin so the imports can be - done normally for modules not in self.exists. + done normally for modules not in self. modules. """ def __init__(self): - self.exists = { - 'sip': True, - 'colorama': True, - 'pypeg2': True, - 'jinja2': True, - 'pygments': True, - 'yaml': True, - 'cssutils': True, - 'typing': True, - 'PyQt5.QtWebEngineWidgets': True, - 'PyQt5.QtWebKitWidgets': True, - 'OpenGL': True, - } + self.modules = collections.OrderedDict([ + ('sip', True), + ('colorama', True), + ('pypeg2', True), + ('jinja2', True), + ('pygments', True), + ('yaml', True), + ('cssutils', True), + ('typing', True), + ('OpenGL', True), + ('PyQt5.QtWebEngineWidgets', True), + ('PyQt5.QtWebKitWidgets', True), + ]) + self.no_version_attribute = ['sip', 'typing', + 'PyQt5.QtWebEngineWidgets', + 'PyQt5.QtWebKitWidgets'] self.version_attribute = '__version__' self.version = '1.2.3' self._real_import = builtins.__import__ @@ -509,10 +513,10 @@ class ImportFake: The imported fake module, or None if normal importing should be used. """ - if name not in self.exists: + if name not in self.modules: # Not one of the modules to test -> use real import return None - elif self.exists[name]: + elif self.modules[name]: ns = types.SimpleNamespace() if self.version_attribute is not None: setattr(ns, self.version_attribute, self.version) @@ -551,14 +555,14 @@ class TestModuleVersions: """Tests for _module_versions().""" - @pytest.mark.usefixtures('import_fake') - def test_all_present(self): + def test_all_present(self, import_fake): """Test with all modules present in version 1.2.3.""" - expected = ['sip: yes', 'colorama: 1.2.3', 'pypeg2: 1.2.3', - 'jinja2: 1.2.3', 'pygments: 1.2.3', 'yaml: 1.2.3', - 'cssutils: 1.2.3', 'typing: yes', 'OpenGL: 1.2.3', - 'PyQt5.QtWebEngineWidgets: yes', - 'PyQt5.QtWebKitWidgets: yes'] + expected = [] + for name in import_fake.modules: + if name in import_fake.no_version_attribute: + expected.append('{}: yes'.format(name)) + else: + expected.append('{}: 1.2.3'.format(name)) assert version._module_versions() == expected @pytest.mark.parametrize('module, idx, expected', [ @@ -574,36 +578,31 @@ class TestModuleVersions: idx: The index where the given text is expected. expected: The expected text. """ - import_fake.exists[module] = False + import_fake.modules[module] = False assert version._module_versions()[idx] == expected - @pytest.mark.parametrize('value, expected', [ - ('VERSION', ['sip: yes', 'colorama: 1.2.3', 'pypeg2: yes', - 'jinja2: yes', 'pygments: yes', 'yaml: yes', - 'cssutils: yes', 'typing: yes', 'OpenGL: yes', - 'PyQt5.QtWebEngineWidgets: yes', - 'PyQt5.QtWebKitWidgets: yes']), - ('SIP_VERSION_STR', ['sip: 1.2.3', 'colorama: yes', 'pypeg2: yes', - 'jinja2: yes', 'pygments: yes', 'yaml: yes', - 'cssutils: yes', 'typing: yes', 'OpenGL: yes', - 'PyQt5.QtWebEngineWidgets: yes', - 'PyQt5.QtWebKitWidgets: yes']), - (None, ['sip: yes', 'colorama: yes', 'pypeg2: yes', 'jinja2: yes', - 'pygments: yes', 'yaml: yes', 'cssutils: yes', 'typing: yes', - 'OpenGL: yes', 'PyQt5.QtWebEngineWidgets: yes', - 'PyQt5.QtWebKitWidgets: yes']), + @pytest.mark.parametrize('attribute, expected_modules', [ + ('VERSION', ['colorama']), + ('SIP_VERSION_STR', ['sip']), + (None, []), ]) - def test_version_attribute(self, value, expected, import_fake): + def test_version_attribute(self, attribute, expected_modules, import_fake): """Test with a different version attribute. VERSION is tested for old colorama versions, and None to make sure things still work if some package suddenly doesn't have __version__. Args: - value: The name of the version attribute. + attribute: The name of the version attribute. expected: The expected return value. """ - import_fake.version_attribute = value + import_fake.version_attribute = attribute + expected = [] + for name in import_fake.modules: + if name in expected_modules: + expected.append('{}: 1.2.3'.format(name)) + else: + expected.append('{}: yes'.format(name)) assert version._module_versions() == expected @pytest.mark.parametrize('name, has_version', [ From d179450c29a9dfbe0eff08ca84fddfbd3967615d Mon Sep 17 00:00:00 2001 From: Christian Helbling Date: Thu, 6 Jul 2017 15:35:52 +0200 Subject: [PATCH 18/25] :fullscreen, enter video fullscreen, :fullscreen, exit video fullscreen should not go into video fullscreen --- qutebrowser/mainwindow/mainwindow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 6edabda09..88ffcf383 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -488,7 +488,7 @@ class MainWindow(QWidget): if on: self.state_before_fullscreen = self.windowState() self.showFullScreen() - else: + elif self.isFullScreen(): self.setWindowState(self.state_before_fullscreen) log.misc.debug('on: {}, state before fullscreen: {}'.format( on, debug.qflags_key(Qt, self.state_before_fullscreen))) From 6a8d2ac826e4f4a02bc183a17aee497a7773aec7 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 6 Jul 2017 23:18:29 +0200 Subject: [PATCH 19/25] Disable search workaround for Qt 5.9.2 --- qutebrowser/browser/webengine/webenginetab.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py index 0a4c2dfc7..79688c870 100644 --- a/qutebrowser/browser/webengine/webenginetab.py +++ b/qutebrowser/browser/webengine/webenginetab.py @@ -715,7 +715,8 @@ class WebEngineTab(browsertab.AbstractTab): @pyqtSlot() def _on_load_started(self): """Clear search when a new load is started if needed.""" - if qtutils.version_check('5.9'): + if (qtutils.version_check('5.9') and + not qtutils.version_check('5.9.2')): # WORKAROUND for # https://bugreports.qt.io/browse/QTBUG-61506 self.search.clear() From 6d9e5dc931bff543eebaf97bb063b7c7c24a0224 Mon Sep 17 00:00:00 2001 From: Christian Helbling Date: Fri, 7 Jul 2017 11:30:18 +0200 Subject: [PATCH 20/25] avoid too long lines --- qutebrowser/browser/commands.py | 7 ++++--- qutebrowser/mainwindow/mainwindow.py | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index 9f7cef9d4..f0585bba0 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -2171,9 +2171,10 @@ class CommandDispatcher: window = self._tabbed_browser.window() if window.isFullScreen(): - window.setWindowState(window.state_before_fullscreen & ~Qt.WindowFullScreen) + window.setWindowState( + window.state_before_fullscreen & ~Qt.WindowFullScreen) else: window.state_before_fullscreen = window.windowState() window.showFullScreen() - log.misc.debug('state before fullscreen: {}' - .format(debug.qflags_key(Qt, window.state_before_fullscreen))) + log.misc.debug('state before fullscreen: {}'.format( + debug.qflags_key(Qt, window.state_before_fullscreen))) diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 88ffcf383..2f43ba58e 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -30,7 +30,8 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication, QSizePolicy from qutebrowser.commands import runners, cmdutils from qutebrowser.config import config -from qutebrowser.utils import message, log, usertypes, qtutils, objreg, utils, debug +from qutebrowser.utils import (message, log, usertypes, qtutils, objreg, utils, + debug) from qutebrowser.mainwindow import tabbedbrowser, messageview, prompt from qutebrowser.mainwindow.statusbar import bar from qutebrowser.completion import completionwidget, completer From 5098aa388b9802c5279322f2500ec19da439bc20 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 7 Jul 2017 14:28:36 +0200 Subject: [PATCH 21/25] build_release: Fail GitHub uploads early --- scripts/dev/build_release.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/scripts/dev/build_release.py b/scripts/dev/build_release.py index e6a4f89e1..6a6adb5bd 100755 --- a/scripts/dev/build_release.py +++ b/scripts/dev/build_release.py @@ -292,6 +292,13 @@ def build_sdist(): return artifacts +def read_github_token(): + """Read the GitHub API token from disk.""" + token_file = os.path.join(os.path.expanduser('~'), '.gh_token') + with open(token_file, encoding='ascii') as f: + token = f.read().strip() + + def github_upload(artifacts, tag): """Upload the given artifacts to GitHub. @@ -302,9 +309,7 @@ def github_upload(artifacts, tag): import github3 utils.print_title("Uploading to github...") - token_file = os.path.join(os.path.expanduser('~'), '.gh_token') - with open(token_file, encoding='ascii') as f: - token = f.read().strip() + token = read_github_token() gh = github3.login(token=token) repo = gh.repository('qutebrowser', 'qutebrowser') @@ -341,6 +346,12 @@ def main(): upload_to_pypi = False + if args.upload is not None: + # Fail early when trying to upload without github3 installed + # or without API token + import github3 + read_github_token() + if os.name == 'nt': if sys.maxsize > 2**32: # WORKAROUND From af6d833c50df281da4b4536d2f1b1215740fa3a7 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 7 Jul 2017 15:18:05 +0200 Subject: [PATCH 22/25] Fix build_release.py --- scripts/dev/build_release.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/dev/build_release.py b/scripts/dev/build_release.py index 6a6adb5bd..bb5733cad 100755 --- a/scripts/dev/build_release.py +++ b/scripts/dev/build_release.py @@ -297,6 +297,7 @@ def read_github_token(): token_file = os.path.join(os.path.expanduser('~'), '.gh_token') with open(token_file, encoding='ascii') as f: token = f.read().strip() + return token def github_upload(artifacts, tag): @@ -349,7 +350,7 @@ def main(): if args.upload is not None: # Fail early when trying to upload without github3 installed # or without API token - import github3 + import github3 # pylint: disable=unused-variable read_github_token() if os.name == 'nt': From 215503ba5901968573562306dbecfc47ef4a85a4 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 7 Jul 2017 15:21:18 +0200 Subject: [PATCH 23/25] Remove now useless suppression --- tests/unit/utils/test_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/utils/test_version.py b/tests/unit/utils/test_version.py index 5623d0ce3..6717cf75b 100644 --- a/tests/unit/utils/test_version.py +++ b/tests/unit/utils/test_version.py @@ -822,7 +822,7 @@ class VersionParams: VersionParams('webkit-ng', with_webkit='ng'), VersionParams('unknown-dist', known_distribution=False), VersionParams('no-ssl', ssl_support=False), -], ids=lambda param: param.name) # pylint: disable=too-many-locals +], ids=lambda param: param.name) def test_version_output(params, stubs, monkeypatch): """Test version.version().""" class FakeWebEngineProfile: From f7dbd3c283f9564d5d19023a0876daf8cedcc217 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 7 Jul 2017 17:58:38 +0200 Subject: [PATCH 24/25] Add initial CODEOWNERS file --- .github/CODEOWNERS | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..f623e0a93 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,10 @@ +* @The-Compiler + +qutebrowser/browser/history.py @The-Compiler @rcorre +qutebrowser/completion/* @The-Compiler @rcorre +qutebrowser/misc/sql.py @The-Compiler @rcorre +tests/end2end/features/completion.feature @The-Compiler @rcorre +tests/end2end/features/test_completion_bdd.py @The-Compiler @rcorre +tests/unit/browser/test_history.py @The-Compiler @rcorre +tests/unit/completion/* @The-Compiler @rcorre +tests/unit/misc/test_sql.py @The-Compiler @rcorre From a572b0f34d3c35d1c584c5fe7926d5b29c52d876 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 7 Jul 2017 18:40:57 +0200 Subject: [PATCH 25/25] Update docs --- CHANGELOG.asciidoc | 6 ++++++ README.asciidoc | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index 15e087c6b..8a41c625e 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -36,6 +36,12 @@ Major changes the entire browsing history. - Completely rewritten configuration system. +Fixes +~~~~~ + +- Exiting fullscreen via `:fullscreen` or buttons on a page now + restores the correct previous window state (maximized/fullscreen). + v0.11.1 (unreleased) -------------------- diff --git a/README.asciidoc b/README.asciidoc index fff189cee..3ed3bc054 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -163,9 +163,9 @@ Contributors, sorted by the number of commits in descending order: * Kevin Velghe * Raphael Pierzina * Joel Torstensson +* Jay Kamat * Patric Schmitz * Tarcisio Fedrizzi -* Jay Kamat * Claude * Philipp Hansch * Fritz Reichwald @@ -211,6 +211,7 @@ Contributors, sorted by the number of commits in descending order: * Halfwit * David Vogt * Claire Cavanaugh +* Christian Helbling * rikn00 * kanikaa1234 * haitaka