Implement full screen

This commit is contained in:
Kovid Goyal 2019-08-07 11:51:54 +05:30
parent 146b5dc6e3
commit 0c7bcb0f8c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 71 additions and 14 deletions

View File

@ -169,7 +169,7 @@ def main(args=sys.argv):
if opts.raise_window:
main.raise_()
if opts.full_screen:
main.showFullScreen()
main.set_full_screen(True)
app.exec_()
if listener is not None:

View File

@ -11,7 +11,9 @@ from collections import defaultdict
from hashlib import sha256
from threading import Thread
from PyQt5.Qt import QDockWidget, QModelIndex, Qt, QVBoxLayout, QWidget, pyqtSignal
from PyQt5.Qt import (
QDockWidget, QEvent, QModelIndex, Qt, QVBoxLayout, QWidget, pyqtSignal
)
from calibre import prints
from calibre.constants import config_dir
@ -43,6 +45,7 @@ class EbookViewer(MainWindow):
def __init__(self):
MainWindow.__init__(self, None)
self.in_full_screen_mode = None
try:
os.makedirs(annotations_dir)
except EnvironmentError:
@ -73,11 +76,13 @@ class EbookViewer(MainWindow):
self.web_view.reload_book.connect(self.reload_book)
self.web_view.toggle_toc.connect(self.toggle_toc)
self.web_view.update_current_toc_nodes.connect(self.toc.update_current_toc_nodes)
self.web_view.toggle_full_screen.connect(self.toggle_full_screen)
self.setCentralWidget(self.web_view)
state = vprefs['main_window_state']
if state:
self.restoreState(state, self.MAIN_WINDOW_STATE_VERSION)
# IPC {{{
def handle_commandline_arg(self, arg):
if arg:
if os.path.isfile(arg) and os.access(arg, os.R_OK):
@ -92,7 +97,28 @@ class EbookViewer(MainWindow):
return
self.load_ebook(path, open_at=open_at)
self.raise_()
# }}}
# Fullscreen {{{
def set_full_screen(self, on):
if on:
self.showFullScreen()
else:
self.showNormal()
def changeEvent(self, ev):
if ev.type() == QEvent.WindowStateChange:
in_full_screen_mode = self.isFullScreen()
if self.in_full_screen_mode is None or self.in_full_screen_mode != in_full_screen_mode:
self.in_full_screen_mode = in_full_screen_mode
self.web_view.notify_full_screen_state_change(self.in_full_screen_mode)
return MainWindow.changeEvent(self, ev)
def toggle_full_screen(self):
self.set_full_screen(not self.isFullScreen())
# }}}
# ToC {{{
def toggle_toc(self):
if self.toc_dock.isVisible():
self.toc_dock.setVisible(False)
@ -106,6 +132,9 @@ class EbookViewer(MainWindow):
def toc_searched(self, index):
item = self.toc_model.itemFromIndex(index)
self.web_view.goto_toc_node(item.node_id)
# }}}
# Load book {{{
def load_ebook(self, pathtoebook, open_at=None, reload_book=False):
# TODO: Implement open_at
@ -166,7 +195,9 @@ class EbookViewer(MainWindow):
with open(path, 'rb') as f:
raw = f.read()
merge_annotations(parse_annotations(raw), amap)
# }}}
# CFI management {{{
def initial_cfi_for_current_book(self):
lrp = self.current_book_data['annotations_map']['last-read']
if lrp:
@ -179,7 +210,9 @@ class EbookViewer(MainWindow):
return
self.current_book_data['annotations_map']['last-read'] = [{
'pos': cfi, 'pos_type': 'epubcfi', 'timestamp': utcnow()}]
# }}}
# State serialization {{{
def save_annotations(self):
if not self.current_book_data:
return
@ -201,3 +234,4 @@ class EbookViewer(MainWindow):
self.save_annotations()
self.save_state()
return MainWindow.closeEvent(self, ev)
# }}}

View File

@ -171,11 +171,13 @@ class ViewerBridge(Bridge):
reload_book = from_js()
toggle_toc = from_js()
update_current_toc_nodes = from_js(object, object)
toggle_full_screen = from_js()
create_view = to_js()
show_preparing_message = to_js()
start_book_load = to_js()
goto_toc_node = to_js()
full_screen_state_changed = to_js()
class WebPage(QWebEnginePage):
@ -252,6 +254,7 @@ class WebView(RestartingWebEngineView):
reload_book = pyqtSignal()
toggle_toc = pyqtSignal()
update_current_toc_nodes = pyqtSignal(object, object)
toggle_full_screen = pyqtSignal()
def __init__(self, parent=None):
self._host_widget = None
@ -267,6 +270,7 @@ class WebView(RestartingWebEngineView):
self.bridge.reload_book.connect(self.reload_book)
self.bridge.toggle_toc.connect(self.toggle_toc)
self.bridge.update_current_toc_nodes.connect(self.update_current_toc_nodes)
self.bridge.toggle_full_screen.connect(self.toggle_full_screen)
self.pending_bridge_ready_actions = {}
self.setPage(self._page)
self.setAcceptDrops(False)
@ -343,6 +347,9 @@ class WebView(RestartingWebEngineView):
def goto_toc_node(self, node_id):
self.execute_when_ready('goto_toc_node', node_id)
def notify_full_screen_state_change(self, in_fullscreen_mode):
self.execute_when_ready('full_screen_state_changed', in_fullscreen_mode)
def set_session_data(self, key, val):
if key == '*' and val is None:
vprefs['session_data'] = {}

View File

@ -62,7 +62,8 @@ register_callback(def():
)
runtime = {
'is_standalone_viewer': False
'is_standalone_viewer': False,
'viewer_in_full_screen': False,
}

View File

@ -216,17 +216,18 @@ class MainOverlay:
sync_action = ac(_('Sync'), _('Get last read position and annotations from the server'), self.overlay.sync_book, 'cloud-download')
delete_action = ac(_('Delete'), _('Delete this book from the device'), self.overlay.delete_book, 'trash')
reload_action = ac(_('Reload'), _('Reload this book from the {}').format( _('computer') if runtime.is_standalone_viewer else _('server')), self.overlay.reload_book, 'refresh')
home_action = ac(_('Home'), _('Return to list of books'), def(): home();, 'home')
back_action = ac(_('Back'), None, self.back, 'arrow-left')
forward_action = ac(_('Forward'), None, self.forward, 'arrow-right')
if runtime.is_standalone_viewer:
reload_actions = E.ul(reload_action)
nav_actions = E.ul(back_action, forward_action)
else:
reload_actions = E.ul(sync_action, delete_action, reload_action)
nav_actions = E.ul(home_action, back_action, forward_action)
actions_div = E.div( # actions
E.ul(
ac(_('Home'), _('Return to list of books'), def(): home();, 'home'),
ac(_('Back'), None, self.back, 'arrow-left'),
ac(_('Forward'), None, self.forward, 'arrow-right'),
),
nav_actions,
E.ul(
ac(_('Search'), _('Search for text in this book'), self.overlay.show_search, 'search'),
@ -247,12 +248,19 @@ class MainOverlay:
class_=MAIN_OVERLAY_ACTIONS_CLASS
)
if not full_screen_element() and not is_ios:
# No fullscreen on iOS, see http://caniuse.com/#search=fullscreen
actions_div.appendChild(
E.ul(
ac(_('Full screen'), _('Enter full screen mode'), def(): request_full_screen(), self.overlay.hide();, 'full-screen'),
))
full_screen_actions = []
if runtime.is_standalone_viewer:
text = _('Exit full screen') if runtime.viewer_in_full_screen else _('Enter full screen')
full_screen_actions.push(
ac(text, '', def(): self.overlay.hide(), ui_operations.toggle_full_screen();, 'full-screen'))
else:
if not full_screen_element() and not is_ios:
# No fullscreen on iOS, see http://caniuse.com/#search=fullscreen
full_screen_actions.push(
ac(_('Full screen'), _('Enter full screen mode'), def(): request_full_screen(), self.overlay.hide();, 'full-screen')
)
if full_screen_actions.length:
actions_div.appendChild(E.ul(*full_screen_actions))
container.appendChild(set_css(E.div(class_=MAIN_OVERLAY_TS_CLASS, # top section
onclick=def (evt):evt.stopPropagation();,

View File

@ -198,6 +198,11 @@ def goto_toc_node(node_id):
view.goto_toc_node(node_id)
@from_python
def full_screen_state_changed(viewer_in_full_screen):
runtime.viewer_in_full_screen = viewer_in_full_screen
def onerror(msg, script_url, line_number, column_number, error_object):
if not error_object:
# cross domain error
@ -246,6 +251,8 @@ if window is window.top:
to_python.toggle_toc()
ui_operations.update_current_toc_nodes = def(current_node_id, top_level_node_id):
to_python.update_current_toc_nodes(current_node_id, top_level_node_id)
ui_operations.toggle_full_screen = def():
to_python.toggle_full_screen()
document.body.appendChild(E.div(id='view'))
window.onerror = onerror
create_modal_container()