mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Populate preview panel when opening/changing editors
This commit is contained in:
parent
087bcee620
commit
53b164d7fb
@ -593,9 +593,10 @@ def parse_html5(raw, decoder=None, log=None, discard_namespaces=False, line_numb
|
|||||||
raise ValueError('Failed to parse correctly, root has tag: %s and prefix: %s' % (root.tag, root.prefix))
|
raise ValueError('Failed to parse correctly, root has tag: %s and prefix: %s' % (root.tag, root.prefix))
|
||||||
return root
|
return root
|
||||||
|
|
||||||
def parse(raw, decoder=None, log=None, line_numbers=True, linenumber_attribute=None):
|
def parse(raw, decoder=None, log=None, line_numbers=True, linenumber_attribute=None, replace_entities=True):
|
||||||
if isinstance(raw, bytes):
|
if isinstance(raw, bytes):
|
||||||
raw = xml_to_unicode(raw)[0] if decoder is None else decoder(raw)
|
raw = xml_to_unicode(raw)[0] if decoder is None else decoder(raw)
|
||||||
|
if replace_entities:
|
||||||
raw = xml_replace_entities(raw).replace('\0', '') # Handle �
|
raw = xml_replace_entities(raw).replace('\0', '') # Handle �
|
||||||
raw = raw.replace('\r\n', '\n').replace('\r', '\n')
|
raw = raw.replace('\r\n', '\n').replace('\r', '\n')
|
||||||
|
|
||||||
|
@ -232,16 +232,16 @@ class Boss(QObject):
|
|||||||
if editor is None:
|
if editor is None:
|
||||||
editor = editors[name] = editor_from_syntax(syntax, self.gui.editor_tabs)
|
editor = editors[name] = editor_from_syntax(syntax, self.gui.editor_tabs)
|
||||||
editor.undo_redo_state_changed.connect(self.editor_undo_redo_state_changed)
|
editor.undo_redo_state_changed.connect(self.editor_undo_redo_state_changed)
|
||||||
self.gui.central.add_editor(name, editor)
|
|
||||||
c = current_container()
|
c = current_container()
|
||||||
with c.open(name) as f:
|
with c.open(name) as f:
|
||||||
editor.data = c.decode(f.read())
|
editor.data = c.decode(f.read())
|
||||||
editor.modification_state_changed.connect(self.editor_modification_state_changed)
|
editor.modification_state_changed.connect(self.editor_modification_state_changed)
|
||||||
|
self.gui.central.add_editor(name, editor)
|
||||||
self.gui.central.show_editor(editor)
|
self.gui.central.show_editor(editor)
|
||||||
|
|
||||||
def edit_file_requested(self, name, syntax, mime):
|
def edit_file_requested(self, name, syntax, mime):
|
||||||
if name in editors:
|
if name in editors:
|
||||||
self.gui.show_editor(editors[name])
|
self.gui.central.show_editor(editors[name])
|
||||||
return
|
return
|
||||||
syntax = syntax or syntax_from_mime(mime)
|
syntax = syntax or syntax_from_mime(mime)
|
||||||
if not syntax:
|
if not syntax:
|
||||||
@ -275,6 +275,13 @@ class Boss(QObject):
|
|||||||
actions['editor-redo'].setEnabled(ed.redo_available)
|
actions['editor-redo'].setEnabled(ed.redo_available)
|
||||||
actions['editor-save'].setEnabled(ed.is_modified)
|
actions['editor-save'].setEnabled(ed.is_modified)
|
||||||
self.gui.keyboard.set_mode(ed.syntax)
|
self.gui.keyboard.set_mode(ed.syntax)
|
||||||
|
name = None
|
||||||
|
for n, x in editors.iteritems():
|
||||||
|
if ed is x:
|
||||||
|
name = n
|
||||||
|
break
|
||||||
|
if name is not None:
|
||||||
|
self.gui.preview.show(name)
|
||||||
else:
|
else:
|
||||||
self.gui.keyboard.set_mode('other')
|
self.gui.keyboard.set_mode('other')
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ from __future__ import (unicode_literals, division, absolute_import,
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
|
import time
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from Queue import Queue, Empty
|
from Queue import Queue, Empty
|
||||||
|
|
||||||
@ -14,7 +15,11 @@ from PyQt4.Qt import (
|
|||||||
QNetworkReply, QTimer, QNetworkRequest, QUrl)
|
QNetworkReply, QTimer, QNetworkRequest, QUrl)
|
||||||
from PyQt4.QtWebKit import QWebView
|
from PyQt4.QtWebKit import QWebView
|
||||||
|
|
||||||
|
from calibre import prints
|
||||||
from calibre.constants import iswindows
|
from calibre.constants import iswindows
|
||||||
|
from calibre.ebooks.oeb.polish.parsing import parse
|
||||||
|
from calibre.ebooks.oeb.base import serialize
|
||||||
|
from calibre.gui2 import Dispatcher
|
||||||
from calibre.gui2.tweak_book import current_container, editors
|
from calibre.gui2.tweak_book import current_container, editors
|
||||||
from calibre.gui2.viewer.documentview import apply_settings
|
from calibre.gui2.viewer.documentview import apply_settings
|
||||||
from calibre.gui2.viewer.config import config
|
from calibre.gui2.viewer.config import config
|
||||||
@ -22,27 +27,36 @@ from calibre.utils.ipc.simple_worker import offload_worker
|
|||||||
|
|
||||||
shutdown = object()
|
shutdown = object()
|
||||||
|
|
||||||
|
def parse_html(raw):
|
||||||
|
root = parse(raw, decoder=lambda x:x.decode('utf-8'), replace_entities=False, line_numbers=True, linenumber_attribute='lnum')
|
||||||
|
return serialize(root, 'text/html').decode('utf-8')
|
||||||
|
|
||||||
class ParseWorker(Thread):
|
class ParseWorker(Thread):
|
||||||
|
|
||||||
daemon = True
|
daemon = True
|
||||||
|
SLEEP_TIME = 1
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, callback=lambda x, y: None):
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
self.worker = offload_worker(priority='low')
|
self.worker = offload_worker(priority='low')
|
||||||
self.requests = Queue()
|
self.requests = Queue()
|
||||||
self.request_count = 0
|
self.request_count = 0
|
||||||
self.start()
|
self.start()
|
||||||
|
self.cache = {}
|
||||||
|
self.callback = callback
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
mod, func = 'calibre.gui2.tweak_book.preview', 'parse_html'
|
||||||
try:
|
try:
|
||||||
# Connect to the worker and send a dummy job to initialize it
|
# Connect to the worker and send a dummy job to initialize it
|
||||||
self.worker(None, None, (), {})
|
self.worker(mod, func, b'<p></p>')
|
||||||
except:
|
except:
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return
|
return
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
time.sleep(self.SLEEP_TIME)
|
||||||
x = self.requests.get()
|
x = self.requests.get()
|
||||||
requests = [x]
|
requests = [x]
|
||||||
while True:
|
while True:
|
||||||
@ -55,7 +69,37 @@ class ParseWorker(Thread):
|
|||||||
break
|
break
|
||||||
request = sorted(requests, reverse=True)[0]
|
request = sorted(requests, reverse=True)[0]
|
||||||
del requests
|
del requests
|
||||||
request
|
name, data = request[1:]
|
||||||
|
old_len, old_fp, old_parsed = self.cache.get(name, (None, None, None))
|
||||||
|
length, fp = len(data), hash(data)
|
||||||
|
if length == old_len and fp == old_fp:
|
||||||
|
self.done(name, old_parsed)
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
res = self.worker(mod, func, data)
|
||||||
|
except:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
else:
|
||||||
|
parsed_data = res['result']
|
||||||
|
if res['tb']:
|
||||||
|
prints("Parser error:")
|
||||||
|
prints(res['tb'])
|
||||||
|
else:
|
||||||
|
self.cache[name] = (length, fp, parsed_data)
|
||||||
|
self.done(name, parsed_data)
|
||||||
|
|
||||||
|
def done(self, name, data):
|
||||||
|
try:
|
||||||
|
self.callback(name, data)
|
||||||
|
except Exception:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
|
||||||
|
def add_request(self, name):
|
||||||
|
data = get_data(name)
|
||||||
|
self.requests.put((self.request_count, name, data))
|
||||||
|
self.request_count += 1
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
self.requests.put(shutdown)
|
self.requests.put(shutdown)
|
||||||
@ -158,12 +202,21 @@ class Preview(QWidget):
|
|||||||
self.l = l = QVBoxLayout()
|
self.l = l = QVBoxLayout()
|
||||||
self.setLayout(l)
|
self.setLayout(l)
|
||||||
l.setContentsMargins(0, 0, 0, 0)
|
l.setContentsMargins(0, 0, 0, 0)
|
||||||
self.parse_worker = ParseWorker()
|
self.parse_worker = ParseWorker(callback=Dispatcher(self.parsing_done))
|
||||||
self.view = WebView(self)
|
self.view = WebView(self)
|
||||||
l.addWidget(self.view)
|
l.addWidget(self.view)
|
||||||
|
|
||||||
|
self.current_name = None
|
||||||
|
self.parse_pending = False
|
||||||
|
self.last_sync_request = None
|
||||||
|
|
||||||
def show(self, name):
|
def show(self, name):
|
||||||
data = get_data(name)
|
self.current_name, self.parse_pending = name, True
|
||||||
|
self.parse_worker.add_request(name)
|
||||||
|
|
||||||
|
def parsing_done(self, name, data):
|
||||||
|
if name == self.current_name:
|
||||||
c = current_container()
|
c = current_container()
|
||||||
self.view.setHtml(data, QUrl.fromLocalFile(c.name_to_abspath(name)))
|
self.view.setHtml(data, QUrl.fromLocalFile(c.name_to_abspath(name)))
|
||||||
|
self.parse_pending = False
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user