Use a QWebEngineView if QtWebEngine is available.
If QtWebEngine is not available replace figure tags with div's to allow
 the QTextEdit to render the rest of the html properly
This commit is contained in:
Timmy Welch 2023-07-01 23:29:38 -07:00
parent 19986b64d0
commit f43f51aa2f
5 changed files with 123 additions and 7 deletions

View File

@ -63,6 +63,14 @@ try:
qt_exception_hook = UncaughtHook()
from comictaggerlib.taggerwindow import TaggerWindow
try:
# needed here to initialize QWebEngine
from PyQt5.QtWebEngineWidgets import QWebEngineView # noqa: F401
qt_webengine_available = True
except ImportError:
qt_webengine_available = False
class Application(QtWidgets.QApplication):
openFileRequest = QtCore.pyqtSignal(QtCore.QUrl, name="openfileRequest")

View File

@ -23,7 +23,7 @@ from comicapi.issuestring import IssueString
from comictaggerlib.coverimagewidget import CoverImageWidget
from comictaggerlib.ctsettings import ct_ns
from comictaggerlib.ui import ui_path
from comictaggerlib.ui.qtutils import reduce_widget_font_size
from comictaggerlib.ui.qtutils import new_web_view, reduce_widget_font_size
from comictalker.comictalker import ComicTalker, TalkerError
from comictalker.resulttypes import ComicIssue
@ -58,6 +58,19 @@ class IssueSelectionWindow(QtWidgets.QDialog):
gridlayout.addWidget(self.coverWidget)
gridlayout.setContentsMargins(0, 0, 0, 0)
self.teDescription: QtWidgets.QWidget
webengine = new_web_view(self)
if webengine:
self.teDescription.hide()
self.teDescription.deleteLater()
# I don't know how to replace teDescription, this is the result of teDescription.height() once rendered
webengine.resize(webengine.width(), 141)
self.splitter.addWidget(webengine)
self.teDescription = webengine
logger.info("successfully loaded QWebEngineView")
else:
logger.info("failed to open QWebEngineView")
reduce_widget_font_size(self.twList)
reduce_widget_font_size(self.teDescription, 1)
@ -189,6 +202,13 @@ class IssueSelectionWindow(QtWidgets.QDialog):
def cell_double_clicked(self, r: int, c: int) -> None:
self.accept()
def set_description(self, widget: QtWidgets.QWidget, text: str) -> None:
if isinstance(widget, QtWidgets.QTextEdit):
widget.setText(text.replace("</figure>", "</div>").replace("<figure", "<div"))
else:
html = text
widget.setHtml(html, QtCore.QUrl(self.talker.website))
def current_item_changed(self, curr: QtCore.QModelIndex | None, prev: QtCore.QModelIndex | None) -> None:
if curr is None:
return
@ -203,8 +223,8 @@ class IssueSelectionWindow(QtWidgets.QDialog):
self.issue_number = record.issue_number
self.coverWidget.set_issue_details(self.issue_id, [record.image_url, *record.alt_image_urls])
if record.description is None:
self.teDescription.setText("")
self.set_description(self.teDescription, "")
else:
self.teDescription.setText(record.description)
self.set_description(self.teDescription, record.description)
break

View File

@ -20,7 +20,7 @@ import logging
from collections import deque
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtCore import QUrl, pyqtSignal
from comicapi import utils
from comicapi.comicarchive import ComicArchive
@ -32,7 +32,7 @@ from comictaggerlib.issueselectionwindow import IssueSelectionWindow
from comictaggerlib.matchselectionwindow import MatchSelectionWindow
from comictaggerlib.progresswindow import IDProgressWindow
from comictaggerlib.ui import ui_path
from comictaggerlib.ui.qtutils import reduce_widget_font_size
from comictaggerlib.ui.qtutils import new_web_view, reduce_widget_font_size
from comictalker.comictalker import ComicTalker, TalkerError
from comictalker.resulttypes import ComicSeries
@ -122,6 +122,16 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
gridlayout.addWidget(self.imageWidget)
gridlayout.setContentsMargins(0, 0, 0, 0)
self.teDetails: QtWidgets.QWidget
webengine = new_web_view(self)
if webengine:
self.teDetails.hide()
self.teDetails.deleteLater()
# I don't know how to replace teDetails, this is the result of teDetails.height() once rendered
webengine.resize(webengine.width(), 141)
self.splitter.addWidget(webengine)
self.teDetails = webengine
reduce_widget_font_size(self.teDetails, 1)
reduce_widget_font_size(self.twList)
@ -533,6 +543,13 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
def cell_double_clicked(self, r: int, c: int) -> None:
self.show_issues()
def set_description(self, widget: QtWidgets.QWidget, text: str) -> None:
if isinstance(widget, QtWidgets.QTextEdit):
widget.setText(text.replace("</figure>", "</div>").replace("<figure", "<div"))
else:
html = text
widget.setHtml(html, QUrl(self.talker.website))
def current_item_changed(self, curr: QtCore.QModelIndex | None, prev: QtCore.QModelIndex | None) -> None:
if curr is None:
return
@ -545,8 +562,8 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
for record in self.ct_search_results:
if record.id == self.series_id:
if record.description is None:
self.teDetails.setText("")
self.set_description(self.teDetails, "")
else:
self.teDetails.setText(record.description)
self.set_description(self.teDetails, record.description)
self.imageWidget.set_url(record.image_url)
break

View File

@ -5,6 +5,10 @@ from __future__ import annotations
import io
import logging
import traceback
import webbrowser
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QWidget
from comictaggerlib.graphics import graphics_path
@ -12,6 +16,7 @@ logger = logging.getLogger(__name__)
try:
from PyQt5 import QtGui, QtWidgets
from PyQt5.QtCore import Qt
qt_available = True
except ImportError:
@ -25,6 +30,68 @@ if qt_available:
except ImportError:
pil_available = False
try:
from PyQt5.QtWebEngineWidgets import QWebEnginePage, QWebEngineView
class WebPage(QWebEnginePage):
def acceptNavigationRequest(
self, url: QUrl, n_type: QWebEnginePage.NavigationType, isMainFrame: bool
) -> bool:
if n_type in (
QWebEnginePage.NavigationType.NavigationTypeOther,
QWebEnginePage.NavigationType.NavigationTypeTyped,
):
return True
if n_type in (QWebEnginePage.NavigationType.NavigationTypeLinkClicked,) and url.scheme() in (
"http",
"https",
):
webbrowser.open(url.toString())
return False
def new_web_view(parent: QWidget) -> QWebEngineView:
webengine = QWebEngineView(parent)
webengine.setPage(WebPage(parent))
webengine.setContextMenuPolicy(Qt.ContextMenuPolicy.NoContextMenu)
settings = webengine.settings()
settings.setAttribute(settings.WebAttribute.AutoLoadImages, True)
settings.setAttribute(settings.WebAttribute.JavascriptEnabled, False)
settings.setAttribute(settings.WebAttribute.JavascriptCanOpenWindows, False)
settings.setAttribute(settings.WebAttribute.JavascriptCanAccessClipboard, False)
settings.setAttribute(settings.WebAttribute.LinksIncludedInFocusChain, False)
settings.setAttribute(settings.WebAttribute.LocalStorageEnabled, False)
settings.setAttribute(settings.WebAttribute.LocalContentCanAccessRemoteUrls, False)
settings.setAttribute(settings.WebAttribute.XSSAuditingEnabled, False)
settings.setAttribute(settings.WebAttribute.SpatialNavigationEnabled, True)
settings.setAttribute(settings.WebAttribute.LocalContentCanAccessFileUrls, False)
settings.setAttribute(settings.WebAttribute.HyperlinkAuditingEnabled, False)
settings.setAttribute(settings.WebAttribute.ScrollAnimatorEnabled, False)
settings.setAttribute(settings.WebAttribute.ErrorPageEnabled, False)
settings.setAttribute(settings.WebAttribute.PluginsEnabled, False)
settings.setAttribute(settings.WebAttribute.FullScreenSupportEnabled, False)
settings.setAttribute(settings.WebAttribute.ScreenCaptureEnabled, False)
settings.setAttribute(settings.WebAttribute.WebGLEnabled, False)
settings.setAttribute(settings.WebAttribute.Accelerated2dCanvasEnabled, False)
settings.setAttribute(settings.WebAttribute.AutoLoadIconsForPage, False)
settings.setAttribute(settings.WebAttribute.TouchIconsEnabled, False)
settings.setAttribute(settings.WebAttribute.FocusOnNavigationEnabled, False)
settings.setAttribute(settings.WebAttribute.PrintElementBackgrounds, False)
settings.setAttribute(settings.WebAttribute.AllowRunningInsecureContent, False)
settings.setAttribute(settings.WebAttribute.AllowGeolocationOnInsecureOrigins, False)
settings.setAttribute(settings.WebAttribute.AllowWindowActivationFromJavaScript, False)
settings.setAttribute(settings.WebAttribute.ShowScrollBars, True)
settings.setAttribute(settings.WebAttribute.PlaybackRequiresUserGesture, True)
settings.setAttribute(settings.WebAttribute.JavascriptCanPaste, False)
settings.setAttribute(settings.WebAttribute.WebRTCPublicInterfacesOnly, False)
settings.setAttribute(settings.WebAttribute.DnsPrefetchEnabled, False)
settings.setAttribute(settings.WebAttribute.PdfViewerEnabled, False)
return webengine
except ImportError:
def new_web_view(parent: QWidget) -> QWebEngineView:
...
def reduce_widget_font_size(widget: QtWidgets.QWidget, delta: int = 2) -> None:
f = widget.font()
if f.pointSize() > 10:

View File

@ -74,8 +74,12 @@ GUI =
PyQt5
ICU =
pyicu;sys_platform == 'linux' or sys_platform == 'darwin'
QTW =
PyQt5
PyQtWebEngine
all =
PyQt5
PyQtWebEngine
py7zr
rarfile>=4.0
pyicu;sys_platform == 'linux' or sys_platform == 'darwin'