Skip to content
Browse files
Drop support for Qt < 5.7.1
See #2742
  • Loading branch information
The-Compiler committed Sep 18, 2017
1 parent 2b43049 commit 852baaa
Show file tree
Hide file tree
Showing 39 changed files with 142 additions and 683 deletions.
@@ -102,18 +102,16 @@ The following software and libraries are required to run qutebrowser:
*[Python] 3.4 or newer (3.6 recommended) - note that
support for Python 3.4[will be dropped soon].
*[Qt] 5.2.0 or newer (5.9 recommended - note that support for Qt
< 5.7.1 will be dropped soon) with the following modules:
*[Qt] 5.7.1 or newer with the following modules:
- QtCore / qtbase
- QtQuick (part of qtbase in some distributions)
- QtSQL (part of qtbase in some distributions)
- QtWebEngine, or
- QtWebKit (old or link:[reloaded]/NG).
Note that support for legacy QtWebKit (before 5.212) will be
dropped soon.
*[PyQt] 5.2.0 or newer
(5.9 recommended) for Python 3. Note that support for PyQt < 5.7 will be
dropped soon.
*[PyQt] 5.7.0 or newer
(5.9 recommended) for Python 3.
@@ -23,7 +23,7 @@ Breaking changes
- (TODO) Support for legacy QtWebKit (before 5.212 which is distributed
independently from Qt) is dropped.
- (TODO) Support for Python 3.4 is dropped.
- (TODO) Support for Qt before 5.7 is dropped.
- Support for Qt before 5.7.1 and PyQt before 5.7 is dropped.
- (TODO) New dependency on ruamel.yaml; dropped PyYAML dependency.
- (TODO) The QtWebEngine backend is now used by default if available.
- New dependency on the QtSql module and Qt sqlite support.
@@ -36,6 +36,7 @@ Breaking changes
work properly anymore.
- Various documentation files got moved to the doc/ subfolder,
`qutebrowser.desktop` got moved to misc/.
- The `--harfbuzz` commandline argument got dropped
Major changes
@@ -205,26 +205,6 @@ Experiencing freezing on sites like duckduckgo and youtube.::
See[Issue #357]
for more details.
Experiencing segfaults (crashes) on Debian systems.::
For Debian it's highly recommended to install the `gstreamer0.10-plugins-base` package.
This is a workaround for a bug in Qt, it has been fixed upstream in Qt 5.4
More details can be found[here].
Segfaults on Facebook, Medium, Amazon, ...::
If you are on a Debian or Ubuntu based system, you might experience some crashes
visiting these sites. This is caused by various bugs in Qt which have been
fixed in Qt 5.4. However Debian and Ubuntu are slow to adopt or upgrade
some packages. On Debian Jessie, it's recommended to use the experimental
repos as described in[the documentation].
Since Ubuntu Trusty (using Qt 5.2.1),[over
70 important bugs] have been fixed in QtWebKit. For Debian Jessie (using Qt 5.3.2)
it's still[nearly
20 important bugs].
When using QtWebEngine, qutebrowser reports "Render Process Crashed" and the console prints a traceback on Gentoo Linux or another Source-Based Distro::
As stated in[GCC's Website] GCC 6 has introduced some optimizations that could break non-conforming codebases, like QtWebEngine. +
As a workaround, you can disable the nullpointer check optimization by adding the -fno-delete-null-pointer-checks flag while compiling. +
@@ -3,39 +3,50 @@ Installing qutebrowser


NOTE: qutebrowser recently had some bigger dependency changes for v1.0.0, which
means those instructions might be out of date in some places.[Please help]
updating them if you notice something being broken!

On Debian / Ubuntu

qutebrowser should run on these systems:
How to install qutebrowser depends a lot on the version of Debian/Ubuntu you're

Debian Jessie / Ubuntu 14.04 LTS / Linux Mint < 18

Those distributions only have Python 3.4 and a too old Qt version available. A
newer Qt isn't easily installable on Python 3.4, unfortunately.

* Debian jessie or newer
* Ubuntu Trusty (14.04 LTS) or newer
* Any other distribution based on these (e.g. Linux Mint 17+)
It should be possible to install Python 3.5 e.g. from the[deadsnakes PPA] or via_ipca[pyenv], but nobody tried that yet.

Unfortunately there is no Debian package in the official repos yet, but installing qutebrowser is
still relatively easy!
If you get qutebrowser running on those distributions, please[contribute]
to update this documentation!

You can use packages that are built for every release or build it yourself from git.
Ubuntu 16.04 LTS / Linux Mint 18

On Ubuntu 16.04 and 16.10 it's recommended to <<tox,install qutebrowser via tox>>
instead in order to be able to use the new QtWebEngine backend. Newer versions
have a QtWebEngine package in the repositories.
Ubuntu 16.04 doesn't come with an up-to-date engine (a new enough QtWebKit, or
QtWebEngine). However, it comes with Python 3.5, so you can
<<tox,install qutebrowser via tox>>.

Using the packages
Debian Stretch / Ubuntu 17.04 and newer

Those versions come with QtWebEngine in the repositories. This makes it possible
to install qutebrowser via the Debian package.

Install the dependencies via apt-get:

# apt-get install python3-lxml python-tox python3-pyqt5 python3-pyqt5.qtwebkit python3-pyqt5.qtquick python3-sip python3-jinja2 python3-pygments python3-yaml python3-pyqt5.qtsql libqt5sql5-sqlite
# apt install python-tox python3-{lxml,pyqt5,sip,jinja2,pygments,yaml} python3-pyqt5.qt{webengine,quick,opengl,sql} libqt5sql5-sqlite

On Debian Stretch or Ubuntu 17.04 or later, it's also recommended to use the
newer QtWebEngine backend.

To do so, install `python3-pyqt5.qtwebengine` and `python3-pyqt5.qtopengl`, then
start qutebrowser with `--backend webengine`.

Get the qutebrowser package from the[release page] and download
the[PyPEG2 package].
@@ -47,35 +58,27 @@ Install the packages:
# dpkg -i qutebrowser_*_all.deb

Build it from git

Install the dependencies via apt-get:

# apt-get install python3-pyqt5 python3-pyqt5.qtwebkit python3-pyqt5.qtquick python-tox python3-sip python3-dev python3-pyqt5.qtsql libqt5sql5-sqlite

On Debian Stretch or Ubuntu 17.04 or later, it's also recommended to install
`python3-pyqt5.qtwebengine` and start qutebrowser with `--backend webengine` in
order to use the new backend.

To generate the documentation for the `:help` command, when using the git
repository (rather than a release):
Some additional hints:

- Alternatively, you can <<tox,install qutebrowser via tox>> to get a newer
QtWebEngine version.
- If running from git, run the following to generate the documentation for the
`:help` command:
# apt-get install asciidoc source-highlight
# apt-get install --no-install-recommends asciidoc source-highlight
$ python3 scripts/
If video or sound don't seem to work, try installing the gstreamer plugins:

- If you prefer using QtWebKit, there's an up-to-date version available in
Debian experimental, or from[this repository]
for Debian Stretch.
- If video or sound don't work with QtWebKit, try installing the gstreamer plugins:
# apt-get install gstreamer1.0-plugins-{bad,base,good,ugly}
Then <<tox,install qutebrowser via tox>>.

On Fedora

@@ -116,7 +119,7 @@ $ rm -r qutebrowser-git

or you could use an AUR helper, e.g. `yaourt -S qutebrowser-git`.

If video or sound don't seem to work, try installing the gstreamer plugins:
If video or sound don't work with QtWebKit, try installing the gstreamer plugins:

# pacman -S gst-plugins-{base,good,bad,ugly} gst-libav
@@ -125,6 +128,8 @@ If video or sound don't seem to work, try installing the gstreamer plugins:
On Gentoo

WARNING: The Gentoo packages (even the live version) are lagging behind a lot, which means those instructions probably won't work anymore. Until things are looking better, it's recommended to <<tox,install qutebrowser via tox>>.

A version of qutebrowser is available in the main repository and can be installed with:

@@ -84,9 +84,6 @@ show it.
Force colored logging

*--harfbuzz* '{old,new,system,auto}'::
HarfBuzz engine version to use. Default: auto.

Silently remove unknown config options.

@@ -27,7 +27,6 @@ markers =
this: Used to mark tests during development
no_invalid_lines: Don't fail on unparseable lines in end2end tests
issue2478: Tests which are broken on Windows with QtWebEngine,
qt55: Tests only running on Qt 5.5 or later
qt_log_level_fail = WARNING
qt_log_ignore =
^SpellCheck: .*
@@ -19,9 +19,6 @@

"""The ListView to display downloads in."""

import functools

import sip
from PyQt5.QtCore import pyqtSlot, QSize, Qt, QTimer
from PyQt5.QtWidgets import QListView, QSizePolicy, QMenu, QStyleFactory

@@ -30,29 +27,6 @@
from qutebrowser.utils import qtutils, utils, objreg

def update_geometry(obj):
"""Weird WORKAROUND for some weird PyQt bug (probably).
This actually should be a method of DownloadView, but for some reason the
rowsInserted/rowsRemoved signals don't get disconnected from this method
when the DownloadView is deleted from Qt (e.g. by closing a window).
Here we check if obj ("self") was deleted and just ignore the event if so.
Original bug:
Workaround bug:
def _update_geometry():
"""Actually update the geometry if the object still exists."""
if sip.isdeleted(obj):

# If we don't use a singleShot QTimer, the geometry isn't updated correctly
# and won't include the new item.
QTimer.singleShot(0, _update_geometry)

class DownloadView(QListView):

"""QListView which shows currently running downloads as a bar.
@@ -85,9 +59,12 @@ def __init__(self, win_id, parent=None):
self._menu = None
model = objreg.get('download-model', scope='window', window=win_id)
model.rowsInserted.connect(functools.partial(update_geometry, self))
model.rowsRemoved.connect(functools.partial(update_geometry, self))
model.dataChanged.connect(functools.partial(update_geometry, self))
QTimer.singleShot(0, self.updateGeometry))
QTimer.singleShot(0, self.updateGeometry))
QTimer.singleShot(0, self.updateGeometry))
@@ -49,7 +49,6 @@ def _set_cache_size(self):
if size is None:
size = 1024 * 1024 * 50 # default from QNetworkDiskCachePrivate
if (qtutils.version_check('5.7.1') and
not qtutils.version_check('5.9')): # pragma: no cover
if not qtutils.version_check('5.9'): # pragma: no cover
size = 0
@@ -37,14 +37,6 @@ def __repr__(self):
self, error=debug.qenum_key(QSslError, self._error.error()),

def __hash__(self):
# Qt >= 5.4
return hash(self._error)
except TypeError:
return hash((self._error.certificate().toDer(),

def __eq__(self, other):
return self._error == other._error # pylint: disable=protected-access

@@ -24,13 +24,12 @@
import netrc
import html

from PyQt5.QtCore import (pyqtSlot, pyqtSignal, PYQT_VERSION, QCoreApplication,
QUrl, QByteArray)
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QCoreApplication, QUrl,
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkReply, QSslSocket

from qutebrowser.config import config
from qutebrowser.utils import (message, log, usertypes, utils, objreg, qtutils,
from qutebrowser.utils import message, log, usertypes, utils, objreg, urlutils
from qutebrowser.browser import shared
from qutebrowser.browser.webkit import certificateerror
from import (webkitqutescheme, networkreply,
@@ -88,15 +87,9 @@ def _is_secure_cipher(cipher):

def init():
"""Disable insecure SSL ciphers on old Qt versions."""
if qtutils.version_check('5.3.0'):
default_ciphers = QSslSocket.defaultCiphers()
log.init.debug("Default Qt ciphers: {}".format(
', '.join( for c in default_ciphers)))
default_ciphers = QSslSocket.supportedCiphers()
log.init.debug("Supported Qt ciphers: {}".format(
', '.join( for c in default_ciphers)))
default_ciphers = QSslSocket.defaultCiphers()
log.init.debug("Default Qt ciphers: {}".format(
', '.join( for c in default_ciphers)))

good_ciphers = []
bad_ciphers = []
@@ -409,24 +402,11 @@ def createRequest(self, op, req, outgoing_data):
tab = objreg.get('tab', scope='tab', window=self._win_id,
current_url = tab.url()
except (KeyError, RuntimeError, TypeError):
except (KeyError, RuntimeError):
# Catching RuntimeError and TypeError because we could be in
# the middle of the webpage shutdown here.
# Catching RuntimeError because we could be in the middle of the
# webpage shutdown here.
current_url = QUrl()

self.set_referer(req, current_url)

if PYQT_VERSION < 0x050301:
# WORKAROUND (remove this when we bump the requirements to 5.3.1)
# If we don't disable our message handler, we get a freeze if a
# warning is printed due to a PyQt bug, e.g. when clicking a
# currency on
# See
with log.disable_qt_msghandler():
reply = super().createRequest(op, req, outgoing_data)
reply = super().createRequest(op, req, outgoing_data)
return reply
return super().createRequest(op, req, outgoing_data)
@@ -292,9 +292,6 @@ def remove_blank_target(self):
elem = elem._parent() # pylint: disable=protected-access

def _move_text_cursor(self):
if self is None:
# old PyQt versions call the slot after the element is deleted.
if self.is_text_input() and self.is_editable():

@@ -33,7 +33,7 @@
from PyQt5.QtWebKit import QWebSettings

from qutebrowser.config import config, websettings
from qutebrowser.utils import standarddir, urlutils, qtutils
from qutebrowser.utils import standarddir, urlutils
from qutebrowser.browser import shared

@@ -131,13 +131,6 @@ def init(_args):
os.path.join(data_path, 'offline-storage'))

if (config.val.content.private_browsing and
not qtutils.version_check('5.4.2')):
# Won't work when private browsing is not enabled globally, but that's
# the best we can do...


0 comments on commit 852baaa

Please sign in to comment.