From 3b1493241b832bc329b6f8e596a66a8e9416d9bc Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Mon, 9 May 2016 14:58:57 +0300 Subject: [PATCH] Make WebKit support optional again QtWebKit has been deprecated upstream, and is no longer part of e.g. the official PyQt Windows installers. --- ReText/tab.py | 71 +++----------------------------- ReText/webkitpreview.py | 90 +++++++++++++++++++++++++++++++++++++++++ ReText/window.py | 5 ++- 3 files changed, 100 insertions(+), 66 deletions(-) create mode 100644 ReText/webkitpreview.py diff --git a/ReText/tab.py b/ReText/tab.py index 3ebafd64..0762f5fc 100644 --- a/ReText/tab.py +++ b/ReText/tab.py @@ -22,7 +22,6 @@ from ReText import app_version, globalSettings, converterprocess from ReText.editor import ReTextEdit from ReText.highlighter import ReTextHighlighter -from ReText.syncscroll import SyncScroll try: from ReText.fakevimeditor import ReTextFakeVimHandler @@ -37,8 +36,11 @@ from PyQt5.QtCore import pyqtSignal, Qt, QDir, QFile, QFileInfo, QPoint, QTextStream, QTimer, QUrl from PyQt5.QtGui import QDesktopServices, QTextCursor, QTextDocument from PyQt5.QtWidgets import QTextBrowser, QTextEdit, QSplitter -from PyQt5.QtWebKit import QWebSettings -from PyQt5.QtWebKitWidgets import QWebPage, QWebView + +try: + from ReText.webkitpreview import ReTextWebPreview +except ImportError: + ReTextWebPreview = None PreviewDisabled, PreviewLive, PreviewNormal = range(3) @@ -248,11 +250,7 @@ def updatePreviewBox(self): newValue = scrollbar.maximum() - distToBottom scrollbar.setValue(newValue) else: - settings = self.previewBox.settings() - settings.setFontFamily(QWebSettings.StandardFont, - globalSettings.font.family()) - settings.setFontSize(QWebSettings.DefaultFontSize, - globalSettings.font.pointSize()) + self.previewBox.updateFontSettings() # Always provide a baseUrl otherwise QWebView will # refuse to show images or other external objects @@ -355,63 +353,6 @@ def find(self, text, flags): return True return False -class ReTextWebPreview(QWebView): - - def __init__(self, editBox, - editorPositionToSourceLineFunc, - sourceLineToEditorPositionFunc): - - QWebView.__init__(self) - - self.editBox = editBox - - if not globalSettings.handleWebLinks: - self.page().setLinkDelegationPolicy(QWebPage.DelegateExternalLinks) - self.page().linkClicked.connect(QDesktopServices.openUrl) - self.settings().setAttribute(QWebSettings.LocalContentCanAccessFileUrls, False) - self.settings().setDefaultTextEncoding('utf-8') - # Avoid caching of CSS - self.settings().setObjectCacheCapacities(0,0,0) - - self.syncscroll = SyncScroll(self.page().mainFrame(), - editorPositionToSourceLineFunc, - sourceLineToEditorPositionFunc) - - # Events relevant to sync scrolling - self.editBox.cursorPositionChanged.connect(self._handleCursorPositionChanged) - self.editBox.verticalScrollBar().valueChanged.connect(self.syncscroll.handleEditorScrolled) - self.editBox.resized.connect(self._handleEditorResized) - - # Scroll the preview when the mouse wheel is used to scroll - # beyond the beginning/end of the editor - self.editBox.scrollLimitReached.connect(self._handleWheelEvent) - - def disconnectExternalSignals(self): - self.editBox.cursorPositionChanged.disconnect(self._handleCursorPositionChanged) - self.editBox.verticalScrollBar().valueChanged.disconnect(self.syncscroll.handleEditorScrolled) - self.editBox.resized.disconnect(self._handleEditorResized) - - self.editBox.scrollLimitReached.disconnect(self._handleWheelEvent) - - def _handleWheelEvent(self, event): - """ - Use this intermediate function because it is not possible to - disconnect a built-in method. It would generate the following error: - TypeError: 'builtin_function_or_method' object is not connected - """ - # Only pass wheelEvents on to the preview if syncscroll is - # controlling the position of the preview - if self.syncscroll.isActive(): - self.wheelEvent(event) - - def _handleCursorPositionChanged(self): - editorCursorPosition = self.editBox.verticalScrollBar().value() + \ - self.editBox.cursorRect().top() - self.syncscroll.handleCursorPositionChanged(editorCursorPosition) - - def _handleEditorResized(self, rect): - self.syncscroll.handleEditorResized(rect.height()) - class ReTextPreview(QTextBrowser): """ diff --git a/ReText/webkitpreview.py b/ReText/webkitpreview.py new file mode 100644 index 00000000..b4debd04 --- /dev/null +++ b/ReText/webkitpreview.py @@ -0,0 +1,90 @@ +# vim: ts=8:sts=8:sw=8:noexpandtab +# +# This file is part of ReText +# Copyright: 2015-2016 Dmitry Shachnev +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +from ReText import globalSettings +from ReText.syncscroll import SyncScroll + +from PyQt5.QtGui import QDesktopServices +from PyQt5.QtWebKit import QWebSettings +from PyQt5.QtWebKitWidgets import QWebPage, QWebView + + +class ReTextWebPreview(QWebView): + + def __init__(self, editBox, + editorPositionToSourceLineFunc, + sourceLineToEditorPositionFunc): + + QWebView.__init__(self) + + self.editBox = editBox + + if not globalSettings.handleWebLinks: + self.page().setLinkDelegationPolicy(QWebPage.DelegateExternalLinks) + self.page().linkClicked.connect(QDesktopServices.openUrl) + self.settings().setAttribute(QWebSettings.LocalContentCanAccessFileUrls, False) + self.settings().setDefaultTextEncoding('utf-8') + # Avoid caching of CSS + self.settings().setObjectCacheCapacities(0,0,0) + + self.syncscroll = SyncScroll(self.page().mainFrame(), + editorPositionToSourceLineFunc, + sourceLineToEditorPositionFunc) + + # Events relevant to sync scrolling + self.editBox.cursorPositionChanged.connect(self._handleCursorPositionChanged) + self.editBox.verticalScrollBar().valueChanged.connect(self.syncscroll.handleEditorScrolled) + self.editBox.resized.connect(self._handleEditorResized) + + # Scroll the preview when the mouse wheel is used to scroll + # beyond the beginning/end of the editor + self.editBox.scrollLimitReached.connect(self._handleWheelEvent) + + def disconnectExternalSignals(self): + self.editBox.cursorPositionChanged.disconnect(self._handleCursorPositionChanged) + self.editBox.verticalScrollBar().valueChanged.disconnect(self.syncscroll.handleEditorScrolled) + self.editBox.resized.disconnect(self._handleEditorResized) + + self.editBox.scrollLimitReached.disconnect(self._handleWheelEvent) + + def _handleWheelEvent(self, event): + """ + Use this intermediate function because it is not possible to + disconnect a built-in method. It would generate the following error: + TypeError: 'builtin_function_or_method' object is not connected + """ + # Only pass wheelEvents on to the preview if syncscroll is + # controlling the position of the preview + if self.syncscroll.isActive(): + self.wheelEvent(event) + + def _handleCursorPositionChanged(self): + editorCursorPosition = self.editBox.verticalScrollBar().value() + \ + self.editBox.cursorRect().top() + self.syncscroll.handleCursorPositionChanged(editorCursorPosition) + + def _handleEditorResized(self, rect): + self.syncscroll.handleEditorResized(rect.height()) + + def updateFontSettings(self): + settings = self.settings() + settings.setFontFamily(QWebSettings.StandardFont, + globalSettings.font.family()) + settings.setFontSize(QWebSettings.DefaultFontSize, + globalSettings.font.pointSize()) diff --git a/ReText/window.py b/ReText/window.py index fb57d3f9..d1ee6158 100644 --- a/ReText/window.py +++ b/ReText/window.py @@ -21,7 +21,7 @@ from subprocess import Popen from ReText import icon_path, app_version, globalSettings, readListFromSettings, \ writeListToSettings, writeToSettings, datadirs -from ReText.tab import ReTextTab, PreviewNormal, PreviewLive +from ReText.tab import ReTextTab, ReTextWebPreview, PreviewNormal, PreviewLive from ReText.dialogs import HtmlDialog, LocaleDialog from ReText.config import ConfigDialog from ReText.icontheme import get_icon_theme @@ -179,6 +179,9 @@ def __init__(self, parent=None): self.actionEnableSC = self.act(self.tr('Enable'), trigbool=self.enableSpellCheck) self.actionSetLocale = self.act(self.tr('Set locale'), trig=self.changeLocale) self.actionWebKit = self.act(self.tr('Use WebKit renderer'), trigbool=self.enableWebKit) + if ReTextWebPreview is None: + globalSettings.useWebKit = False + self.actionWebKit.setEnabled(False) self.actionWebKit.setChecked(globalSettings.useWebKit) self.actionShow = self.act(self.tr('Show directory'), 'system-file-manager', self.showInDir) self.actionFind = self.act(self.tr('Next'), 'go-next', self.find,