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():
|
||||
from gui2.main_window import option_parser
|
||||
from calibre.gui2.main_window import option_parser
|
||||
parser = option_parser(_('''\
|
||||
%prog [options] file
|
||||
|
||||
View an e-book.
|
||||
'''))
|
||||
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 '
|
||||
'front when started.'))
|
||||
a('--full-screen', '--fullscreen', '-f', default=False, action='store_true',
|
||||
@ -168,6 +168,10 @@ def main(args=sys.argv):
|
||||
t.daemon = True
|
||||
t.start()
|
||||
QTimer.singleShot(0, acc.flush)
|
||||
if opts.raise_window:
|
||||
main.raise_()
|
||||
if opts.full_screen:
|
||||
main.showFullScreen()
|
||||
|
||||
app.exec_()
|
||||
if listener is not None:
|
||||
|
@ -5,18 +5,34 @@
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
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.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):
|
||||
|
||||
msg_from_anotherinstance = pyqtSignal(object)
|
||||
book_prepared = pyqtSignal(object, object)
|
||||
|
||||
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):
|
||||
if arg and os.path.isfile(arg) and os.access(arg, os.R_OK):
|
||||
@ -29,3 +45,28 @@ class EbookViewer(MainWindow):
|
||||
return
|
||||
self.load_ebook(path, open_at=open_at)
|
||||
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 PyQt5.Qt import QApplication, QBuffer, QByteArray
|
||||
import os
|
||||
|
||||
from PyQt5.Qt import QApplication, QBuffer, QByteArray, QSize
|
||||
from PyQt5.QtWebEngineCore import QWebEngineUrlSchemeHandler
|
||||
from PyQt5.QtWebEngineWidgets import (
|
||||
QWebEnginePage, QWebEngineProfile, QWebEngineScript
|
||||
)
|
||||
|
||||
from calibre import prints
|
||||
from calibre import as_unicode, prints
|
||||
from calibre.constants import (
|
||||
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 (
|
||||
Bridge, RestartingWebEngineView, create_script, from_js, insert_scripts,
|
||||
secure_webengine, to_js
|
||||
@ -28,8 +31,22 @@ except ImportError:
|
||||
# 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):
|
||||
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):
|
||||
@ -46,24 +63,26 @@ class UrlSchemeHandler(QWebEngineUrlSchemeHandler):
|
||||
rq.fail(rq.UrlNotFound)
|
||||
return
|
||||
name = url.path()[1:]
|
||||
try:
|
||||
data, mime_type = get_data(name)
|
||||
if data is None:
|
||||
rq.fail(rq.UrlNotFound)
|
||||
return
|
||||
if isinstance(data, type('')):
|
||||
data = data.encode('utf-8')
|
||||
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.send_reply(rq, mime_type, data)
|
||||
except Exception:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
rq.fail(rq.RequestFailed)
|
||||
if name.startswith('book/'):
|
||||
name = name.partition('/')[2]
|
||||
try:
|
||||
data, mime_type = get_data(name)
|
||||
if data is None:
|
||||
rq.fail(rq.UrlNotFound)
|
||||
return
|
||||
if isinstance(data, type('')):
|
||||
data = data.encode('utf-8')
|
||||
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.send_reply(rq, mime_type, data)
|
||||
except Exception:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
rq.fail(rq.RequestFailed)
|
||||
|
||||
def send_reply(self, rq, mime_type, data):
|
||||
if sip.isdeleted(rq):
|
||||
@ -151,3 +170,24 @@ class WebView(RestartingWebEngineView):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
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