Edit Book: Fix a regression in the previous release that broke the Live CSS tool

This commit is contained in:
Kovid Goyal 2016-12-24 11:35:56 +05:30
parent 344864a807
commit a2c02acfe0
3 changed files with 28 additions and 50 deletions

View File

@ -32,6 +32,7 @@ is64bit = sys.maxsize > (1 << 32)
isworker = 'CALIBRE_WORKER' in os.environ or 'CALIBRE_SIMPLE_WORKER' in os.environ isworker = 'CALIBRE_WORKER' in os.environ or 'CALIBRE_SIMPLE_WORKER' in os.environ
if isworker: if isworker:
os.environ.pop('CALIBRE_FORCE_ANSI', None) os.environ.pop('CALIBRE_FORCE_ANSI', None)
FAKE_PROTOCOL, FAKE_HOST = 'https', 'calibre-internal.invalid'
try: try:
preferred_encoding = locale.getpreferredencoding() preferred_encoding = locale.getpreferredencoding()

View File

@ -11,10 +11,10 @@ import json
from PyQt5.Qt import ( from PyQt5.Qt import (
QWidget, QTimer, QStackedLayout, QLabel, QScrollArea, QVBoxLayout, QWidget, QTimer, QStackedLayout, QLabel, QScrollArea, QVBoxLayout,
QPainter, Qt, QPalette, QRect, QSize, QSizePolicy, pyqtSignal, QPainter, Qt, QPalette, QRect, QSize, QSizePolicy, pyqtSignal,
QColor, QMenu, QApplication, QIcon) QColor, QMenu, QApplication, QIcon, QUrl)
from calibre.constants import iswindows from calibre.constants import FAKE_HOST, FAKE_PROTOCOL
from calibre.gui2.tweak_book import editors, actions, current_container, tprefs from calibre.gui2.tweak_book import editors, actions, tprefs
from calibre.gui2.tweak_book.editor.themes import get_theme, theme_color from calibre.gui2.tweak_book.editor.themes import get_theme, theme_color
from calibre.gui2.tweak_book.editor.text import default_font_family from calibre.gui2.tweak_book.editor.text import default_font_family
from css_selectors import parse, SelectorError from css_selectors import parse, SelectorError
@ -518,12 +518,11 @@ class LiveCSS(QWidget):
rule['properties'] = properties rule['properties'] = properties
href = rule['href'] href = rule['href']
if hasattr(href, 'startswith') and href.startswith('file://'): if hasattr(href, 'startswith') and href.startswith('%s://%s' % (FAKE_PROTOCOL, FAKE_HOST)):
href = href[len('file://'):] qurl = QUrl(href)
if iswindows and href.startswith('/'): name = qurl.path()[1:]
href = href[1:] if name:
if href: rule['href'] = name
rule['href'] = current_container().abspath_to_name(href, root=self.preview.current_root)
@property @property
def current_name(self): def current_name(self):
@ -568,4 +567,3 @@ class LiveCSS(QWidget):
editor.goto_css_rule(data['rule_address']) editor.goto_css_rule(data['rule_address'])
elif data['type'] == 'elem': elif data['type'] == 'elem':
editor.goto_css_rule(data['rule_address'], sourceline_address=data['sourceline_address']) editor.goto_css_rule(data['rule_address'], sourceline_address=data['sourceline_address'])

View File

@ -17,15 +17,14 @@ from urlparse import urlparse
from PyQt5.Qt import ( from PyQt5.Qt import (
QWidget, QVBoxLayout, QApplication, QSize, QNetworkAccessManager, QMenu, QIcon, QWidget, QVBoxLayout, QApplication, QSize, QNetworkAccessManager, QMenu, QIcon,
QNetworkReply, QTimer, QNetworkRequest, QUrl, Qt, QNetworkDiskCache, QToolBar, QNetworkReply, QTimer, QNetworkRequest, QUrl, Qt, QToolBar,
pyqtSlot, pyqtSignal) pyqtSlot, pyqtSignal)
from PyQt5.QtWebKitWidgets import QWebView, QWebInspector, QWebPage from PyQt5.QtWebKitWidgets import QWebView, QWebInspector, QWebPage
from calibre import prints from calibre import prints
from calibre.constants import iswindows from calibre.constants import FAKE_PROTOCOL, FAKE_HOST
from calibre.ebooks.oeb.polish.parsing import parse from calibre.ebooks.oeb.polish.parsing import parse
from calibre.ebooks.oeb.base import serialize, OEB_DOCS from calibre.ebooks.oeb.base import serialize, OEB_DOCS
from calibre.ptempfile import PersistentTemporaryDirectory
from calibre.gui2 import error_dialog, open_url, NO_URL_FORMATTING from calibre.gui2 import error_dialog, open_url, NO_URL_FORMATTING
from calibre.gui2.tweak_book import current_container, editors, tprefs, actions, TOP from calibre.gui2.tweak_book import current_container, editors, tprefs, actions, TOP
from calibre.gui2.viewer.documentview import apply_settings from calibre.gui2.viewer.documentview import apply_settings
@ -169,6 +168,12 @@ class NetworkReply(QNetworkReply):
data = data.encode('utf-8') data = data.encode('utf-8')
mime_type += '; charset=utf-8' mime_type += '; charset=utf-8'
self.__data = data self.__data = data
mime_type = {
# Prevent warning in console about mimetype of fonts
'application/vnd.ms-opentype':'application/x-font-ttf',
'application/x-font-truetype':'application/x-font-ttf',
'application/font-sfnt': 'application/x-font-ttf',
}.get(mime_type, mime_type)
self.setHeader(QNetworkRequest.ContentTypeHeader, mime_type) self.setHeader(QNetworkRequest.ContentTypeHeader, mime_type)
self.setHeader(QNetworkRequest.ContentLengthHeader, len(self.__data)) self.setHeader(QNetworkRequest.ContentLengthHeader, len(self.__data))
QTimer.singleShot(0, self.finalize_reply) QTimer.singleShot(0, self.finalize_reply)
@ -220,25 +225,11 @@ class NetworkAccessManager(QNetworkAccessManager):
'Custom') 'Custom')
} }
def __init__(self, *args):
QNetworkAccessManager.__init__(self, *args)
self.current_root = None
self.cache = QNetworkDiskCache(self)
self.setCache(self.cache)
self.cache.setCacheDirectory(PersistentTemporaryDirectory(prefix='disk_cache_'))
self.cache.setMaximumCacheSize(0)
def createRequest(self, operation, request, data): def createRequest(self, operation, request, data):
url = unicode(request.url().toString(NO_URL_FORMATTING)) qurl = request.url()
if operation == self.GetOperation and url.startswith('file://'): if operation == self.GetOperation and qurl.host() == FAKE_HOST:
path = url[7:] name = qurl.path()[1:]
if iswindows and path.startswith('/'):
path = path[1:]
c = current_container() c = current_container()
try:
name = c.abspath_to_name(path, root=self.current_root)
except ValueError: # Happens on windows with absolute paths on different drives
name = None
if c.has_name(name): if c.has_name(name):
try: try:
return NetworkReply(self, request, c.mime_map.get(name, 'application/octet-stream'), name) return NetworkReply(self, request, c.mime_map.get(name, 'application/octet-stream'), name)
@ -295,15 +286,6 @@ class WebPage(QWebPage):
self.mainFrame().javaScriptWindowObjectCleared.connect(self.init_javascript) self.mainFrame().javaScriptWindowObjectCleared.connect(self.init_javascript)
self.init_javascript() self.init_javascript()
@dynamic_property
def current_root(self):
def fget(self):
return self.networkAccessManager().current_root
def fset(self, val):
self.networkAccessManager().current_root = val
return property(fget=fget, fset=fset)
def javaScriptConsoleMessage(self, msg, lineno, source_id): def javaScriptConsoleMessage(self, msg, lineno, source_id):
prints('preview js:%s:%s:'%(unicode(source_id), lineno), unicode(msg)) prints('preview js:%s:%s:'%(unicode(source_id), lineno), unicode(msg))
@ -416,11 +398,6 @@ class WebView(QWebView):
only, it is not intended to simulate an actual ebook reader. Some only, it is not intended to simulate an actual ebook reader. Some
aspects of your ebook will not work, such as page breaks and page margins. aspects of your ebook will not work, such as page breaks and page margins.
''')) '''))
self.page().current_root = None
def setUrl(self, qurl):
self.page().current_root = current_container().root
return QWebView.setUrl(self, qurl)
def inspect(self): def inspect(self):
self.inspector.parent().show() self.inspector.parent().show()
@ -559,13 +536,19 @@ class Preview(QWidget):
error_dialog(self, _('Failed to launch worker'), _( error_dialog(self, _('Failed to launch worker'), _(
'Failed to launch the worker process used for rendering the preview'), det_msg=tb, show=True) 'Failed to launch the worker process used for rendering the preview'), det_msg=tb, show=True)
def name_to_qurl(self, name=None):
name = name or self.current_name
qurl = QUrl()
qurl.setScheme(FAKE_PROTOCOL), qurl.setAuthority(FAKE_HOST), qurl.setPath('/' + name)
return qurl
def show(self, name): def show(self, name):
if name != self.current_name: if name != self.current_name:
self.refresh_timer.stop() self.refresh_timer.stop()
self.current_name = name self.current_name = name
self.report_worker_launch_error() self.report_worker_launch_error()
parse_worker.add_request(name) parse_worker.add_request(name)
self.view.setUrl(QUrl.fromLocalFile(current_container().name_to_abspath(name))) self.view.setUrl(self.name_to_qurl())
return True return True
def refresh(self): def refresh(self):
@ -576,7 +559,7 @@ class Preview(QWidget):
self.report_worker_launch_error() self.report_worker_launch_error()
parse_worker.add_request(self.current_name) parse_worker.add_request(self.current_name)
# Tell webkit to reload all html and associated resources # Tell webkit to reload all html and associated resources
current_url = QUrl.fromLocalFile(current_container().name_to_abspath(self.current_name)) current_url = self.name_to_qurl()
self.refresh_starting.emit() self.refresh_starting.emit()
if current_url != self.view.url(): if current_url != self.view.url():
# The container was changed # The container was changed
@ -589,10 +572,6 @@ class Preview(QWidget):
self.view.clear() self.view.clear()
self.current_name = None self.current_name = None
@property
def current_root(self):
return self.view.page().current_root
@property @property
def is_visible(self): def is_visible(self):
return actions['preview-dock'].isChecked() return actions['preview-dock'].isChecked()