mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Viewer: Make it easier to use the bookmarks panel with only keyboard. Fixes #1847423 [[Feature] Make ebook viewer keyboard-friendly](https://bugs.launchpad.net/calibre/+bug/1847423)
This commit is contained in:
parent
e2ded28390
commit
21df277dc4
@ -13,6 +13,7 @@ from PyQt5.Qt import (
|
||||
|
||||
from calibre.gui2 import choose_files, choose_save_file
|
||||
from calibre.gui2.viewer.annotations import serialize_annotation
|
||||
from calibre.gui2.viewer.shortcuts import get_shortcut_for
|
||||
from calibre.srv.render_book import parse_annotation
|
||||
from calibre.utils.date import EPOCH, utcnow
|
||||
from calibre.utils.icu import sort_key
|
||||
@ -69,6 +70,7 @@ class BookmarkManager(QWidget):
|
||||
edited = pyqtSignal(object)
|
||||
activated = pyqtSignal(object)
|
||||
create_requested = pyqtSignal()
|
||||
toggle_requested = pyqtSignal()
|
||||
|
||||
def __init__(self, parent):
|
||||
QWidget.__init__(self, parent)
|
||||
@ -102,7 +104,7 @@ class BookmarkManager(QWidget):
|
||||
b.clicked.connect(self.delete_bookmark)
|
||||
l.addWidget(b, l.rowCount() - 1, 1)
|
||||
|
||||
self.button_delete = b = QPushButton(_('Sort by &name'), self)
|
||||
self.button_delete = b = QPushButton(_('Sort by na&me'), self)
|
||||
b.setToolTip(_('Sort bookmarks by name'))
|
||||
b.clicked.connect(self.sort_by_name)
|
||||
l.addWidget(b)
|
||||
@ -281,3 +283,9 @@ class BookmarkManager(QWidget):
|
||||
self.set_bookmarks(bookmarks)
|
||||
self.set_current_bookmark(bm)
|
||||
self.edited.emit(bookmarks)
|
||||
|
||||
def keyPressEvent(self, ev):
|
||||
if ev.key() == Qt.Key_Escape or get_shortcut_for(self, ev) == 'toggle_bookmarks':
|
||||
self.toggle_requested.emit()
|
||||
return
|
||||
return QWidget.keyPressEvent(self, ev)
|
||||
|
36
src/calibre/gui2/viewer/shortcuts.py
Normal file
36
src/calibre/gui2/viewer/shortcuts.py
Normal file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python2
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
from PyQt5.Qt import QKeySequence, QMainWindow, Qt
|
||||
|
||||
|
||||
def get_main_window_for(widget):
|
||||
p = widget
|
||||
while p is not None:
|
||||
if isinstance(p, QMainWindow):
|
||||
return p
|
||||
p = p.parent()
|
||||
|
||||
|
||||
def key_to_text(key):
|
||||
return QKeySequence(key).toString(QKeySequence.PortableText).lower()
|
||||
|
||||
|
||||
def ev_to_index(ev):
|
||||
m = ev.modifiers()
|
||||
mods = []
|
||||
for x in ('ALT', 'CTRL', 'META', 'SHIFT'):
|
||||
mods.append('y' if m & getattr(Qt, x) else 'n')
|
||||
return ''.join(mods) + key_to_text(ev.key())
|
||||
|
||||
|
||||
def get_shortcut_for(widget, ev):
|
||||
mw = get_main_window_for(widget)
|
||||
if mw is None:
|
||||
return
|
||||
smap = mw.web_view.shortcut_map
|
||||
idx = ev_to_index(ev)
|
||||
return smap.get(idx)
|
@ -120,8 +120,9 @@ class EbookViewer(MainWindow):
|
||||
connect_lambda(
|
||||
w.create_requested, self,
|
||||
lambda self: self.web_view.get_current_cfi(self.bookmarks_widget.create_new_bookmark))
|
||||
self.bookmarks_widget.edited.connect(self.bookmarks_edited)
|
||||
self.bookmarks_widget.activated.connect(self.bookmark_activated)
|
||||
w.edited.connect(self.bookmarks_edited)
|
||||
w.activated.connect(self.bookmark_activated)
|
||||
w.toggle_requested.connect(self.toggle_bookmarks)
|
||||
self.bookmarks_dock.setWidget(w)
|
||||
|
||||
self.web_view = WebView(self)
|
||||
@ -200,7 +201,12 @@ class EbookViewer(MainWindow):
|
||||
self.toc_dock.setVisible(not self.toc_dock.isVisible())
|
||||
|
||||
def toggle_bookmarks(self):
|
||||
self.bookmarks_dock.setVisible(not self.bookmarks_dock.isVisible())
|
||||
is_visible = self.bookmarks_dock.isVisible()
|
||||
self.bookmarks_dock.setVisible(not is_visible)
|
||||
if is_visible:
|
||||
self.web_view.setFocus(Qt.OtherFocusReason)
|
||||
else:
|
||||
self.bookmarks_widget.bookmarks_list.setFocus(Qt.OtherFocusReason)
|
||||
|
||||
def toggle_lookup(self):
|
||||
self.lookup_dock.setVisible(not self.lookup_dock.isVisible())
|
||||
|
@ -235,6 +235,7 @@ class ViewerBridge(Bridge):
|
||||
overlay_visibility_changed = from_js(object)
|
||||
show_loading_message = from_js(object)
|
||||
show_error = from_js(object, object, object)
|
||||
export_shortcut_map = from_js(object)
|
||||
|
||||
create_view = to_js()
|
||||
start_book_load = to_js()
|
||||
@ -405,6 +406,8 @@ class WebView(RestartingWebEngineView):
|
||||
self.bridge.overlay_visibility_changed.connect(self.overlay_visibility_changed)
|
||||
self.bridge.show_loading_message.connect(self.show_loading_message)
|
||||
self.bridge.show_error.connect(self.show_error)
|
||||
self.bridge.export_shortcut_map.connect(self.set_shortcut_map)
|
||||
self.shortcut_map = {}
|
||||
self.bridge.report_cfi.connect(self.call_callback)
|
||||
self.bridge.change_background_image.connect(self.change_background_image)
|
||||
self.pending_bridge_ready_actions = {}
|
||||
@ -416,6 +419,9 @@ class WebView(RestartingWebEngineView):
|
||||
self.inspector = Inspector(parent.inspector_dock.toggleViewAction(), self)
|
||||
parent.inspector_dock.setWidget(self.inspector)
|
||||
|
||||
def set_shortcut_map(self, smap):
|
||||
self.shortcut_map = smap
|
||||
|
||||
def url_changed(self, url):
|
||||
if url.hasFragment():
|
||||
frag = url.fragment(url.FullyDecoded)
|
||||
|
@ -155,6 +155,8 @@ class View:
|
||||
self.book_scrollbar = BookScrollbar(self)
|
||||
sd = get_session_data()
|
||||
self.keyboard_shortcut_map = create_shortcut_map(sd.get('keyboard_shortcuts'))
|
||||
if ui_operations.export_shortcut_map:
|
||||
ui_operations.export_shortcut_map(self.keyboard_shortcut_map)
|
||||
left_margin = E.div(svgicon('caret-left'), style='width:{}px;'.format(sd.get('margin_left', 20)), class_='book-side-margin', id='book-left-margin', onclick=self.left_margin_clicked)
|
||||
set_left_margin_handler(left_margin)
|
||||
right_margin = E.div(svgicon('caret-right'), style='width:{}px;'.format(sd.get('margin_right', 20)), class_='book-side-margin', id='book-right-margin', onclick=self.right_margin_clicked)
|
||||
@ -580,6 +582,8 @@ class View:
|
||||
# redisplay_book() is called when settings are changed
|
||||
sd = get_session_data()
|
||||
self.keyboard_shortcut_map = create_shortcut_map(sd.get('keyboard_shortcuts'))
|
||||
if ui_operations.export_shortcut_map:
|
||||
ui_operations.export_shortcut_map(self.keyboard_shortcut_map)
|
||||
self.book_scrollbar.apply_visibility()
|
||||
self.display_book(self.book)
|
||||
|
||||
|
@ -316,6 +316,8 @@ if window is window.top:
|
||||
to_python.overlay_visibility_changed(visible)
|
||||
ui_operations.show_loading_message = def(msg):
|
||||
to_python.show_loading_message(msg)
|
||||
ui_operations.export_shortcut_map = def(smap):
|
||||
to_python.export_shortcut_map(smap)
|
||||
|
||||
document.body.appendChild(E.div(id='view'))
|
||||
window.onerror = onerror
|
||||
|
Loading…
x
Reference in New Issue
Block a user