mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
More work on the new viewer
This commit is contained in:
parent
559adc51a2
commit
7b75c67e15
@ -96,14 +96,14 @@ def ensure_single_instance(args, open_at):
|
|||||||
|
|
||||||
|
|
||||||
def option_parser():
|
def option_parser():
|
||||||
from gui2.main_window import option_parser
|
from calibre.gui2.main_window import option_parser
|
||||||
parser = option_parser(_('''\
|
parser = option_parser(_('''\
|
||||||
%prog [options] file
|
%prog [options] file
|
||||||
|
|
||||||
View an e-book.
|
View an e-book.
|
||||||
'''))
|
'''))
|
||||||
a = parser.add_option
|
a = parser.add_option
|
||||||
a('--raise-window', default=False, action='strore_true',
|
a('--raise-window', default=False, action='store_true',
|
||||||
help=_('If specified, viewer window will try to come to the '
|
help=_('If specified, viewer window will try to come to the '
|
||||||
'front when started.'))
|
'front when started.'))
|
||||||
a('--full-screen', '--fullscreen', '-f', default=False, action='store_true',
|
a('--full-screen', '--fullscreen', '-f', default=False, action='store_true',
|
||||||
@ -168,6 +168,10 @@ def main(args=sys.argv):
|
|||||||
t.daemon = True
|
t.daemon = True
|
||||||
t.start()
|
t.start()
|
||||||
QTimer.singleShot(0, acc.flush)
|
QTimer.singleShot(0, acc.flush)
|
||||||
|
if opts.raise_window:
|
||||||
|
main.raise_()
|
||||||
|
if opts.full_screen:
|
||||||
|
main.showFullScreen()
|
||||||
|
|
||||||
app.exec_()
|
app.exec_()
|
||||||
if listener is not None:
|
if listener is not None:
|
||||||
|
@ -5,18 +5,34 @@
|
|||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
from PyQt5.Qt import pyqtSignal
|
from PyQt5.Qt import QDockWidget, Qt, pyqtSignal
|
||||||
|
|
||||||
|
from calibre.gui2 import error_dialog
|
||||||
from calibre.gui2.main_window import MainWindow
|
from calibre.gui2.main_window import MainWindow
|
||||||
|
from calibre.gui2.viewer2.convert_book import prepare_book
|
||||||
|
from calibre.gui2.viewer2.web_view import WebView, set_book_path
|
||||||
|
from calibre.utils.ipc.simple_worker import WorkerError
|
||||||
|
|
||||||
|
|
||||||
class EbookViewer(MainWindow):
|
class EbookViewer(MainWindow):
|
||||||
|
|
||||||
msg_from_anotherinstance = pyqtSignal(object)
|
msg_from_anotherinstance = pyqtSignal(object)
|
||||||
|
book_prepared = pyqtSignal(object, object)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
MainWindow.__init__(self)
|
MainWindow.__init__(self, None)
|
||||||
|
self.book_prepared.connect(self.load_finished, type=Qt.QueuedConnection)
|
||||||
|
self.web_view = WebView(self)
|
||||||
|
self.setCentralWidget(self.web_view)
|
||||||
|
|
||||||
|
def create_dock(title, name, areas=Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea):
|
||||||
|
ans = QDockWidget(title, self)
|
||||||
|
ans.setObjectName(name)
|
||||||
|
ans.close()
|
||||||
|
|
||||||
|
self.toc_dock = create_dock(_('Table of Contents'), 'toc-dock')
|
||||||
|
|
||||||
def handle_commandline_arg(self, arg):
|
def handle_commandline_arg(self, arg):
|
||||||
if arg and os.path.isfile(arg) and os.access(arg, os.R_OK):
|
if arg and os.path.isfile(arg) and os.access(arg, os.R_OK):
|
||||||
@ -29,3 +45,28 @@ class EbookViewer(MainWindow):
|
|||||||
return
|
return
|
||||||
self.load_ebook(path, open_at=open_at)
|
self.load_ebook(path, open_at=open_at)
|
||||||
self.raise_()
|
self.raise_()
|
||||||
|
|
||||||
|
def load_ebook(self, pathtoebook, open_at=None):
|
||||||
|
# TODO: Implement open_at
|
||||||
|
t = Thread(name='LoadBook', target=self._load_ebook_worker, args=(pathtoebook, open_at))
|
||||||
|
t.daemon = True
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def _load_ebook_worker(self, pathtoebook, open_at):
|
||||||
|
try:
|
||||||
|
ans = prepare_book(pathtoebook)
|
||||||
|
except WorkerError as e:
|
||||||
|
self.book_prepared.emit(False, {'exception': e, 'tb': e.orig_tb, 'pathtoebook': pathtoebook})
|
||||||
|
except Exception as e:
|
||||||
|
import traceback
|
||||||
|
self.book_prepared.emit(False, {'exception': e, 'tb': traceback.format_exc(), 'pathtoebook': pathtoebook})
|
||||||
|
else:
|
||||||
|
self.book_prepared.emit(True, {'base': ans, 'pathtoebook': pathtoebook, 'open_at': open_at})
|
||||||
|
|
||||||
|
def load_finished(self, ok, data):
|
||||||
|
if not ok:
|
||||||
|
error_dialog(self, _('Loading book failed'), _(
|
||||||
|
'Failed to open the book at {0}. Click "Show details" for more info.').format(data['pathtoebook']),
|
||||||
|
det_msg=data['tb'], show=True)
|
||||||
|
return
|
||||||
|
set_book_path(data['base'])
|
||||||
|
@ -4,17 +4,20 @@
|
|||||||
|
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
from PyQt5.Qt import QApplication, QBuffer, QByteArray
|
import os
|
||||||
|
|
||||||
|
from PyQt5.Qt import QApplication, QBuffer, QByteArray, QSize
|
||||||
from PyQt5.QtWebEngineCore import QWebEngineUrlSchemeHandler
|
from PyQt5.QtWebEngineCore import QWebEngineUrlSchemeHandler
|
||||||
from PyQt5.QtWebEngineWidgets import (
|
from PyQt5.QtWebEngineWidgets import (
|
||||||
QWebEnginePage, QWebEngineProfile, QWebEngineScript
|
QWebEnginePage, QWebEngineProfile, QWebEngineScript
|
||||||
)
|
)
|
||||||
|
|
||||||
from calibre import prints
|
from calibre import as_unicode, prints
|
||||||
from calibre.constants import (
|
from calibre.constants import (
|
||||||
FAKE_HOST, FAKE_PROTOCOL, __version__, is_running_from_develop
|
FAKE_HOST, FAKE_PROTOCOL, __version__, is_running_from_develop
|
||||||
)
|
)
|
||||||
from calibre.gui2 import open_url
|
from calibre.ebooks.oeb.polish.utils import guess_type
|
||||||
|
from calibre.gui2 import error_dialog, open_url
|
||||||
from calibre.gui2.webengine import (
|
from calibre.gui2.webengine import (
|
||||||
Bridge, RestartingWebEngineView, create_script, from_js, insert_scripts,
|
Bridge, RestartingWebEngineView, create_script, from_js, insert_scripts,
|
||||||
secure_webengine, to_js
|
secure_webengine, to_js
|
||||||
@ -28,8 +31,22 @@ except ImportError:
|
|||||||
# Override network access to load data from the book {{{
|
# Override network access to load data from the book {{{
|
||||||
|
|
||||||
|
|
||||||
|
def set_book_path(path=None):
|
||||||
|
set_book_path.path = os.path.abspath(path)
|
||||||
|
|
||||||
|
|
||||||
def get_data(name):
|
def get_data(name):
|
||||||
raise NotImplementedError('TODO: implement this')
|
bdir = getattr(set_book_path, 'path', None)
|
||||||
|
if bdir is None:
|
||||||
|
return None, None
|
||||||
|
path = os.path.abspath(os.path.join(bdir, name))
|
||||||
|
if not path.startswith(bdir):
|
||||||
|
return None, None
|
||||||
|
try:
|
||||||
|
with lopen(path, 'rb') as f:
|
||||||
|
return f.read(), guess_type(name)
|
||||||
|
except EnvironmentError as err:
|
||||||
|
prints('Failed to read from book file: {} with error: {}'.format(name, as_unicode(err)))
|
||||||
|
|
||||||
|
|
||||||
class UrlSchemeHandler(QWebEngineUrlSchemeHandler):
|
class UrlSchemeHandler(QWebEngineUrlSchemeHandler):
|
||||||
@ -46,24 +63,26 @@ class UrlSchemeHandler(QWebEngineUrlSchemeHandler):
|
|||||||
rq.fail(rq.UrlNotFound)
|
rq.fail(rq.UrlNotFound)
|
||||||
return
|
return
|
||||||
name = url.path()[1:]
|
name = url.path()[1:]
|
||||||
try:
|
if name.startswith('book/'):
|
||||||
data, mime_type = get_data(name)
|
name = name.partition('/')[2]
|
||||||
if data is None:
|
try:
|
||||||
rq.fail(rq.UrlNotFound)
|
data, mime_type = get_data(name)
|
||||||
return
|
if data is None:
|
||||||
if isinstance(data, type('')):
|
rq.fail(rq.UrlNotFound)
|
||||||
data = data.encode('utf-8')
|
return
|
||||||
mime_type = {
|
if isinstance(data, type('')):
|
||||||
# Prevent warning in console about mimetype of fonts
|
data = data.encode('utf-8')
|
||||||
'application/vnd.ms-opentype':'application/x-font-ttf',
|
mime_type = {
|
||||||
'application/x-font-truetype':'application/x-font-ttf',
|
# Prevent warning in console about mimetype of fonts
|
||||||
'application/font-sfnt': 'application/x-font-ttf',
|
'application/vnd.ms-opentype':'application/x-font-ttf',
|
||||||
}.get(mime_type, mime_type)
|
'application/x-font-truetype':'application/x-font-ttf',
|
||||||
self.send_reply(rq, mime_type, data)
|
'application/font-sfnt': 'application/x-font-ttf',
|
||||||
except Exception:
|
}.get(mime_type, mime_type)
|
||||||
import traceback
|
self.send_reply(rq, mime_type, data)
|
||||||
traceback.print_exc()
|
except Exception:
|
||||||
rq.fail(rq.RequestFailed)
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
rq.fail(rq.RequestFailed)
|
||||||
|
|
||||||
def send_reply(self, rq, mime_type, data):
|
def send_reply(self, rq, mime_type, data):
|
||||||
if sip.isdeleted(rq):
|
if sip.isdeleted(rq):
|
||||||
@ -151,3 +170,24 @@ class WebView(RestartingWebEngineView):
|
|||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
RestartingWebEngineView.__init__(self, parent)
|
RestartingWebEngineView.__init__(self, parent)
|
||||||
|
self.dead_renderer_error_shown = False
|
||||||
|
self.render_process_failed.connect(self.render_process_died)
|
||||||
|
w = QApplication.instance().desktop().availableGeometry(self).width()
|
||||||
|
self._size_hint = QSize(int(w/3), int(w/2))
|
||||||
|
self._page = WebPage(self)
|
||||||
|
self.setPage(self._page)
|
||||||
|
self.setAcceptDrops(False)
|
||||||
|
|
||||||
|
def render_process_died(self):
|
||||||
|
if self.dead_renderer_error_shown:
|
||||||
|
return
|
||||||
|
self.dead_renderer_error_shown = True
|
||||||
|
error_dialog(self, _('Render process crashed'), _(
|
||||||
|
'The Qt WebEngine Render process has crashed.'
|
||||||
|
' You should try restarting the viewer.') , show=True)
|
||||||
|
|
||||||
|
def sizeHint(self):
|
||||||
|
return self._size_hint
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self.pageAction(QWebEnginePage.Reload).trigger()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user