Improve error dialogs when QtWebKit/QtWebEngine was not found
This commit is contained in:
parent
093f34183c
commit
fa902c5d82
@ -22,15 +22,16 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import functools
|
import functools
|
||||||
|
import html
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt
|
||||||
from PyQt5.QtWidgets import (QApplication, QDialog, QPushButton, QHBoxLayout,
|
from PyQt5.QtWidgets import (QApplication, QDialog, QPushButton, QHBoxLayout,
|
||||||
QVBoxLayout, QLabel)
|
QVBoxLayout, QLabel, QMessageBox)
|
||||||
|
|
||||||
from qutebrowser.config import config
|
from qutebrowser.config import config
|
||||||
from qutebrowser.utils import usertypes, objreg, version
|
from qutebrowser.utils import usertypes, objreg, version, qtutils
|
||||||
from qutebrowser.misc import objects
|
from qutebrowser.misc import objects, msgbox
|
||||||
|
|
||||||
|
|
||||||
_Result = usertypes.enum('_Result', ['quit', 'restart'], is_int=True,
|
_Result = usertypes.enum('_Result', ['quit', 'restart'], is_int=True,
|
||||||
@ -67,8 +68,8 @@ class _Dialog(QDialog):
|
|||||||
"<p>qutebrowser tried to start with the {backend} backend but "
|
"<p>qutebrowser tried to start with the {backend} backend but "
|
||||||
"failed because {because}.</p>{text}"
|
"failed because {because}.</p>{text}"
|
||||||
"<p><b>Forcing the {other_backend.name} backend</b></p>"
|
"<p><b>Forcing the {other_backend.name} backend</b></p>"
|
||||||
"<p>This forces usage of the {other_backend.name} backend. "
|
"<p>This forces usage of the {other_backend.name} backend by "
|
||||||
"This sets the <i>backend = '{other_setting}'</i> setting "
|
"setting the <i>backend = '{other_setting}'</i> option "
|
||||||
"(if you have a <i>config.py</i> file, you'll need to set "
|
"(if you have a <i>config.py</i> file, you'll need to set "
|
||||||
"this manually).</p>".format(
|
"this manually).</p>".format(
|
||||||
backend=backend.name, because=because, text=text,
|
backend=backend.name, because=because, text=text,
|
||||||
@ -101,6 +102,8 @@ class _Dialog(QDialog):
|
|||||||
def _change_setting(self, setting, value):
|
def _change_setting(self, setting, value):
|
||||||
"""Change the given setting and restart."""
|
"""Change the given setting and restart."""
|
||||||
config.instance.set_obj(setting, value, save_yaml=True)
|
config.instance.set_obj(setting, value, save_yaml=True)
|
||||||
|
save_manager = objreg.get('save-manager')
|
||||||
|
save_manager.save_all(is_exit=True)
|
||||||
self.done(_Result.restart)
|
self.done(_Result.restart)
|
||||||
|
|
||||||
|
|
||||||
@ -110,13 +113,15 @@ def _show_dialog(*args, **kwargs):
|
|||||||
|
|
||||||
status = dialog.exec_()
|
status = dialog.exec_()
|
||||||
|
|
||||||
if status == _Result.quit:
|
if status in [_Result.quit, QDialog.Rejected]:
|
||||||
sys.exit(usertypes.Exit.err_init)
|
sys.exit(usertypes.Exit.err_init)
|
||||||
elif status == _Result.restart:
|
elif status == _Result.restart:
|
||||||
# FIXME pass --backend webengine
|
# FIXME pass --backend webengine
|
||||||
quitter = objreg.get('quitter')
|
quitter = objreg.get('quitter')
|
||||||
quitter.restart()
|
quitter.restart()
|
||||||
sys.exit(usertypes.Exit.err_init)
|
sys.exit(usertypes.Exit.err_init)
|
||||||
|
else:
|
||||||
|
assert False, status
|
||||||
|
|
||||||
|
|
||||||
def _handle_nouveau_graphics():
|
def _handle_nouveau_graphics():
|
||||||
@ -143,7 +148,7 @@ def _handle_nouveau_graphics():
|
|||||||
"<p>This allows you to use the newer QtWebEngine backend (based "
|
"<p>This allows you to use the newer QtWebEngine backend (based "
|
||||||
"on Chromium) but could have noticable performance impact "
|
"on Chromium) but could have noticable performance impact "
|
||||||
"(depending on your hardware). "
|
"(depending on your hardware). "
|
||||||
"This sets the <i>force_software_rendering = True</i> setting "
|
"This sets the <i>force_software_rendering = True</i> option "
|
||||||
"(if you have a <i>config.py</i> file, you'll need to set this "
|
"(if you have a <i>config.py</i> file, you'll need to set this "
|
||||||
"manually).</p>",
|
"manually).</p>",
|
||||||
buttons=[button],
|
buttons=[button],
|
||||||
@ -174,7 +179,101 @@ def _handle_wayland():
|
|||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
||||||
|
@attr.s
|
||||||
|
class BackendImports:
|
||||||
|
|
||||||
|
"""Whether backend modules could be imported."""
|
||||||
|
|
||||||
|
webkit_available = attr.ib(default=None)
|
||||||
|
webengine_available = attr.ib(default=None)
|
||||||
|
webkit_error = attr.ib(default=None)
|
||||||
|
webengine_error = attr.ib(default=None)
|
||||||
|
|
||||||
|
|
||||||
|
def _try_import_backends():
|
||||||
|
"""Check whether backends can be imported and return BackendImports."""
|
||||||
|
results = BackendImports()
|
||||||
|
|
||||||
|
try:
|
||||||
|
from PyQt5 import QtWebKit
|
||||||
|
from PyQt5 import QtWebKitWidgets
|
||||||
|
except ImportError as e:
|
||||||
|
results.webkit_available = False
|
||||||
|
results.webkit_error = str(e)
|
||||||
|
else:
|
||||||
|
if qtutils.is_new_qtwebkit():
|
||||||
|
results.webkit_available = True
|
||||||
|
else:
|
||||||
|
results.webkit_available = False
|
||||||
|
results.webkit_error = "Unsupported legacy QtWebKit found"
|
||||||
|
|
||||||
|
try:
|
||||||
|
from PyQt5 import QtWebEngineWidgets
|
||||||
|
except ImportError as e:
|
||||||
|
results.webengine_available = False
|
||||||
|
results.webengine_error = str(e)
|
||||||
|
else:
|
||||||
|
results.webengine_available = True
|
||||||
|
|
||||||
|
assert results.webkit_available is not None
|
||||||
|
assert results.webengine_available is not None
|
||||||
|
if not results.webkit_available:
|
||||||
|
assert results.webkit_error is not None
|
||||||
|
if not results.webengine_available:
|
||||||
|
assert results.webengine_error is not None
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
def _check_backend_modules():
|
||||||
|
"""Check for the modules needed for QtWebKit/QtWebEngine."""
|
||||||
|
imports = _try_import_backends()
|
||||||
|
|
||||||
|
if imports.webkit_available and imports.webengine_available:
|
||||||
|
return
|
||||||
|
elif not imports.webkit_available and not imports.webengine_available:
|
||||||
|
text = ("<p>qutebrowser needs QtWebKit or QtWebEngine, but neither "
|
||||||
|
"could be imported!</p>"
|
||||||
|
"<p>The errors encountered were:<ul>"
|
||||||
|
"<li><b>QtWebKit:</b> {webkit_error}"
|
||||||
|
"<li><b>QtWebEngine:</b> {webengine_error}"
|
||||||
|
"</ul></p>".format(
|
||||||
|
webkit_error=html.escape(imports.webkit_error),
|
||||||
|
webengine_error=html.escape(imports.webengine_error)))
|
||||||
|
errbox = msgbox.msgbox(parent=None,
|
||||||
|
title="No backend library found!",
|
||||||
|
text=text,
|
||||||
|
icon=QMessageBox.Critical,
|
||||||
|
plain_text=False)
|
||||||
|
errbox.exec_()
|
||||||
|
sys.exit(usertypes.Exit.err_init)
|
||||||
|
elif objects.backend == usertypes.Backend.QtWebKit:
|
||||||
|
if imports.webkit_available:
|
||||||
|
return
|
||||||
|
assert imports.webengine_available
|
||||||
|
_show_dialog(
|
||||||
|
backend=usertypes.Backend.QtWebKit,
|
||||||
|
because="QtWebKit could not be imported",
|
||||||
|
text="<p><b>The error encountered was:</b><br/>{}</p>".format(
|
||||||
|
html.escape(imports.webkit_error))
|
||||||
|
)
|
||||||
|
elif objects.backend == usertypes.Backend.QtWebEngine:
|
||||||
|
if imports.webengine_available:
|
||||||
|
return
|
||||||
|
assert imports.webkit_available
|
||||||
|
_show_dialog(
|
||||||
|
backend=usertypes.Backend.QtWebEngine,
|
||||||
|
because="QtWebEngine could not be imported",
|
||||||
|
text="<p><b>The error encountered was:</b><br/>{}</p>".format(
|
||||||
|
html.escape(imports.webengine_error))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Should never be reached
|
||||||
|
assert False
|
||||||
|
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
|
_check_backend_modules()
|
||||||
if objects.backend == usertypes.Backend.QtWebEngine:
|
if objects.backend == usertypes.Backend.QtWebEngine:
|
||||||
_handle_wayland()
|
_handle_wayland()
|
||||||
_handle_nouveau_graphics()
|
_handle_nouveau_graphics()
|
||||||
|
@ -247,35 +247,6 @@ def check_libraries():
|
|||||||
_check_modules(modules)
|
_check_modules(modules)
|
||||||
|
|
||||||
|
|
||||||
def check_backend_libraries(backend):
|
|
||||||
"""Make sure the libraries needed by the given backend are available.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
backend: The backend as usertypes.Backend member.
|
|
||||||
"""
|
|
||||||
from qutebrowser.utils import usertypes
|
|
||||||
if backend == usertypes.Backend.QtWebEngine:
|
|
||||||
modules = {
|
|
||||||
'PyQt5.QtWebEngineWidgets':
|
|
||||||
_missing_str("QtWebEngine", webengine=True),
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
assert backend == usertypes.Backend.QtWebKit, backend
|
|
||||||
modules = {
|
|
||||||
'PyQt5.QtWebKit': _missing_str("PyQt5.QtWebKit"),
|
|
||||||
'PyQt5.QtWebKitWidgets': _missing_str("PyQt5.QtWebKitWidgets"),
|
|
||||||
}
|
|
||||||
_check_modules(modules)
|
|
||||||
|
|
||||||
|
|
||||||
def check_new_webkit(backend):
|
|
||||||
"""Make sure we use QtWebEngine or a new QtWebKit."""
|
|
||||||
from qutebrowser.utils import usertypes, qtutils
|
|
||||||
if backend == usertypes.Backend.QtWebKit and not qtutils.is_new_qtwebkit():
|
|
||||||
_die("qutebrowser does not support legacy QtWebKit versions anymore, "
|
|
||||||
"see the installation docs for details.")
|
|
||||||
|
|
||||||
|
|
||||||
def remove_inputhook():
|
def remove_inputhook():
|
||||||
"""Remove the PyQt input hook.
|
"""Remove the PyQt input hook.
|
||||||
|
|
||||||
@ -338,6 +309,4 @@ def init_with_backend(backend):
|
|||||||
"""
|
"""
|
||||||
assert not isinstance(backend, str), backend
|
assert not isinstance(backend, str), backend
|
||||||
assert backend is not None
|
assert backend is not None
|
||||||
check_backend_libraries(backend)
|
|
||||||
check_backend_ssl_support(backend)
|
check_backend_ssl_support(backend)
|
||||||
check_new_webkit(backend)
|
|
||||||
|
@ -164,6 +164,11 @@ class SaveManager(QObject):
|
|||||||
self.saveables[name].save(is_exit=is_exit, explicit=explicit,
|
self.saveables[name].save(is_exit=is_exit, explicit=explicit,
|
||||||
silent=silent, force=force)
|
silent=silent, force=force)
|
||||||
|
|
||||||
|
def save_all(self, *args, **kwargs):
|
||||||
|
"""Save all saveables."""
|
||||||
|
for saveable in self.saveables:
|
||||||
|
self.save(saveable, *args, **kwargs)
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def autosave(self):
|
def autosave(self):
|
||||||
"""Slot used when the configs are auto-saved."""
|
"""Slot used when the configs are auto-saved."""
|
||||||
|
Loading…
Reference in New Issue
Block a user