mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
Work on highlights panel
This commit is contained in:
parent
9e88dfd3b4
commit
e4a19c8808
44
src/calibre/gui2/viewer/highlights.py
Normal file
44
src/calibre/gui2/viewer/highlights.py
Normal file
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python2
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
from PyQt5.Qt import QListWidget, QListWidgetItem, Qt, QVBoxLayout, QWidget
|
||||
|
||||
from calibre.gui2.viewer.search import SearchInput
|
||||
|
||||
|
||||
class Highlights(QListWidget):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QListWidget.__init__(self, parent)
|
||||
self.setFocusPolicy(Qt.NoFocus)
|
||||
self.setSpacing(2)
|
||||
|
||||
def load(self, highlights):
|
||||
self.clear()
|
||||
for h in highlights:
|
||||
i = QListWidgetItem(h['highlighted_text'], self)
|
||||
i.setData(Qt.UserRole, h)
|
||||
|
||||
|
||||
class HighlightsPanel(QWidget):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QWidget.__init__(self, parent)
|
||||
self.l = l = QVBoxLayout(self)
|
||||
l.setContentsMargins(0, 0, 0, 0)
|
||||
self.search_input = si = SearchInput(self, 'highlights-search')
|
||||
si.do_search.connect(self.search_requested)
|
||||
l.addWidget(si)
|
||||
|
||||
self.highlights = h = Highlights(self)
|
||||
l.addWidget(h)
|
||||
self.load = h.load
|
||||
|
||||
def search_requested(self, query):
|
||||
pass
|
||||
|
||||
def focus(self):
|
||||
self.highlights_list.setFocus(Qt.OtherFocusReason)
|
@ -225,7 +225,7 @@ class SearchInput(QWidget): # {{{
|
||||
|
||||
do_search = pyqtSignal(object)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, parent=None, panel_name='search'):
|
||||
QWidget.__init__(self, parent)
|
||||
self.ignore_search_type_changes = False
|
||||
self.l = l = QVBoxLayout(self)
|
||||
@ -235,7 +235,8 @@ class SearchInput(QWidget): # {{{
|
||||
l.addLayout(h)
|
||||
|
||||
self.search_box = sb = SearchBox(self)
|
||||
sb.initialize('viewer-search-panel-expression')
|
||||
self.panel_name = panel_name
|
||||
sb.initialize('viewer-{}-panel-expression'.format(panel_name))
|
||||
sb.item_selected.connect(self.saved_search_selected)
|
||||
sb.history_saved.connect(self.history_saved)
|
||||
sb.lineEdit().setPlaceholderText(_('Search'))
|
||||
@ -271,35 +272,35 @@ class SearchInput(QWidget): # {{{
|
||||
'<li><b>Whole words</b> will search for whole words that equal the entered text.'
|
||||
'<li><b>Regex</b> will interpret the text as a regular expression.'
|
||||
)))
|
||||
qt.setCurrentIndex(qt.findData(vprefs.get('viewer-search-mode', 'normal') or 'normal'))
|
||||
qt.setCurrentIndex(qt.findData(vprefs.get('viewer-{}-mode'.format(self.panel_name), 'normal') or 'normal'))
|
||||
qt.currentIndexChanged.connect(self.save_search_type)
|
||||
h.addWidget(qt)
|
||||
|
||||
self.case_sensitive = cs = QCheckBox(_('&Case sensitive'), self)
|
||||
cs.setFocusPolicy(Qt.NoFocus)
|
||||
cs.setChecked(bool(vprefs.get('viewer-search-case-sensitive', False)))
|
||||
cs.setChecked(bool(vprefs.get('viewer-{}-case-sensitive'.format(self.panel_name), False)))
|
||||
cs.stateChanged.connect(self.save_search_type)
|
||||
h.addWidget(cs)
|
||||
|
||||
def history_saved(self, new_text, history):
|
||||
if new_text:
|
||||
sss = vprefs.get('saved-search-settings') or {}
|
||||
sss = vprefs.get('saved-{}-settings'.format(self.panel_name)) or {}
|
||||
sss[new_text] = {'case_sensitive': self.case_sensitive.isChecked(), 'mode': self.query_type.currentData()}
|
||||
history = frozenset(history)
|
||||
sss = {k: v for k, v in iteritems(sss) if k in history}
|
||||
vprefs['saved-search-settings'] = sss
|
||||
vprefs['saved-{}-settings'.format(self.panel_name)] = sss
|
||||
|
||||
def save_search_type(self):
|
||||
text = self.search_box.currentText()
|
||||
if text and not self.ignore_search_type_changes:
|
||||
sss = vprefs.get('saved-search-settings') or {}
|
||||
sss = vprefs.get('saved-{}-settings'.format(self.panel_name)) or {}
|
||||
sss[text] = {'case_sensitive': self.case_sensitive.isChecked(), 'mode': self.query_type.currentData()}
|
||||
vprefs['saved-search-settings'] = sss
|
||||
vprefs['saved-{}-settings'.format(self.panel_name)] = sss
|
||||
|
||||
def saved_search_selected(self):
|
||||
text = self.search_box.currentText()
|
||||
if text:
|
||||
s = (vprefs.get('saved-search-settings') or {}).get(text)
|
||||
s = (vprefs.get('saved-{}-settings'.format(self.panel_name)) or {}).get(text)
|
||||
if s:
|
||||
self.ignore_search_type_changes = True
|
||||
if 'case_sensitive' in s:
|
||||
@ -320,8 +321,8 @@ class SearchInput(QWidget): # {{{
|
||||
)
|
||||
|
||||
def emit_search(self, backwards=False):
|
||||
vprefs['viewer-search-case-sensitive'] = self.case_sensitive.isChecked()
|
||||
vprefs['viewer-search-mode'] = self.query_type.currentData()
|
||||
vprefs['viewer-{}-case-sensitive'.format(self.panel_name)] = self.case_sensitive.isChecked()
|
||||
vprefs['viewer-{}-mode'.format(self.panel_name)] = self.query_type.currentData()
|
||||
sq = self.search_query(backwards)
|
||||
if sq is not None:
|
||||
self.do_search.emit(sq)
|
||||
|
@ -32,6 +32,7 @@ from calibre.gui2.viewer.bookmarks import BookmarkManager
|
||||
from calibre.gui2.viewer.convert_book import (
|
||||
clean_running_workers, prepare_book, update_book
|
||||
)
|
||||
from calibre.gui2.viewer.highlights import HighlightsPanel
|
||||
from calibre.gui2.viewer.lookup import Lookup
|
||||
from calibre.gui2.viewer.overlay import LoadingOverlay
|
||||
from calibre.gui2.viewer.search import SearchPanel
|
||||
@ -73,6 +74,7 @@ def dock_defs():
|
||||
d(_('Bookmarks'), 'bookmarks', Qt.RightDockWidgetArea)
|
||||
d(_('Search'), 'search', Qt.LeftDockWidgetArea)
|
||||
d(_('Inspector'), 'inspector', Qt.RightDockWidgetArea, Qt.AllDockWidgetAreas)
|
||||
d(_('Highlights'), 'highlights', Qt.RightDockWidgetArea)
|
||||
return ans
|
||||
|
||||
|
||||
@ -152,6 +154,9 @@ class EbookViewer(MainWindow):
|
||||
w.toggle_requested.connect(self.toggle_bookmarks)
|
||||
self.bookmarks_dock.setWidget(w)
|
||||
|
||||
self.highlights_widget = w = HighlightsPanel(self)
|
||||
self.highlights_dock.setWidget(w)
|
||||
|
||||
self.web_view = WebView(self)
|
||||
self.web_view.cfi_changed.connect(self.cfi_changed)
|
||||
self.web_view.reload_book.connect(self.reload_book)
|
||||
@ -161,6 +166,7 @@ class EbookViewer(MainWindow):
|
||||
self.search_widget.show_search_result.connect(self.web_view.show_search_result)
|
||||
self.web_view.search_result_not_found.connect(self.search_widget.search_result_not_found)
|
||||
self.web_view.toggle_bookmarks.connect(self.toggle_bookmarks)
|
||||
self.web_view.toggle_highlights.connect(self.toggle_highlights)
|
||||
self.web_view.new_bookmark.connect(self.bookmarks_widget.create_requested)
|
||||
self.web_view.toggle_inspector.connect(self.toggle_inspector)
|
||||
self.web_view.toggle_lookup.connect(self.toggle_lookup)
|
||||
@ -301,6 +307,14 @@ class EbookViewer(MainWindow):
|
||||
else:
|
||||
self.bookmarks_widget.bookmarks_list.setFocus(Qt.OtherFocusReason)
|
||||
|
||||
def toggle_highlights(self):
|
||||
is_visible = self.highlights_dock.isVisible()
|
||||
self.highlights_dock.setVisible(not is_visible)
|
||||
if is_visible:
|
||||
self.web_view.setFocus(Qt.OtherFocusReason)
|
||||
else:
|
||||
self.highlights_widget.focus()
|
||||
|
||||
def toggle_lookup(self):
|
||||
self.lookup_dock.setVisible(not self.lookup_dock.isVisible())
|
||||
|
||||
@ -490,9 +504,11 @@ class EbookViewer(MainWindow):
|
||||
initial_position = {'type': 'ref', 'data': open_at[len('ref:'):]}
|
||||
elif is_float(open_at):
|
||||
initial_position = {'type': 'bookpos', 'data': float(open_at)}
|
||||
highlights = self.current_book_data['annotations_map']['highlight']
|
||||
self.highlights_widget.load(highlights)
|
||||
self.web_view.start_book_load(
|
||||
initial_position=initial_position,
|
||||
highlights=list(map(serialize_annotation, self.current_book_data['annotations_map']['highlight']))
|
||||
highlights=list(map(serialize_annotation, highlights))
|
||||
)
|
||||
|
||||
def load_book_data(self):
|
||||
|
@ -248,6 +248,7 @@ class ViewerBridge(Bridge):
|
||||
reload_book = from_js()
|
||||
toggle_toc = from_js()
|
||||
toggle_bookmarks = from_js()
|
||||
toggle_highlights = from_js()
|
||||
new_bookmark = from_js()
|
||||
toggle_inspector = from_js()
|
||||
toggle_lookup = from_js()
|
||||
@ -439,6 +440,7 @@ class WebView(RestartingWebEngineView):
|
||||
search_result_not_found = pyqtSignal(object)
|
||||
find_next = pyqtSignal(object)
|
||||
toggle_bookmarks = pyqtSignal()
|
||||
toggle_highlights = pyqtSignal()
|
||||
new_bookmark = pyqtSignal()
|
||||
toggle_inspector = pyqtSignal()
|
||||
toggle_lookup = pyqtSignal()
|
||||
@ -491,6 +493,7 @@ class WebView(RestartingWebEngineView):
|
||||
self.bridge.search_result_not_found.connect(self.search_result_not_found)
|
||||
self.bridge.find_next.connect(self.find_next)
|
||||
self.bridge.toggle_bookmarks.connect(self.toggle_bookmarks)
|
||||
self.bridge.toggle_highlights.connect(self.toggle_highlights)
|
||||
self.bridge.new_bookmark.connect(self.new_bookmark)
|
||||
self.bridge.toggle_inspector.connect(self.toggle_inspector)
|
||||
self.bridge.toggle_lookup.connect(self.toggle_lookup)
|
||||
|
@ -333,12 +333,11 @@ def shortcuts_definition():
|
||||
}
|
||||
if runtime.in_develop_mode:
|
||||
ans.create_annotation = desc(
|
||||
"a",
|
||||
"Ctrl+h",
|
||||
'ui',
|
||||
_('Create a highlight'),
|
||||
)
|
||||
|
||||
|
||||
return ans
|
||||
|
||||
|
||||
@ -398,6 +397,12 @@ def add_standalone_viewer_shortcuts():
|
||||
'ui',
|
||||
_('Toggle the toolbar'),
|
||||
)
|
||||
if runtime.in_develop_mode:
|
||||
sc['toggle_highlights'] = desc(
|
||||
"Ctrl+Alt+h",
|
||||
'ui',
|
||||
_('Toggle the highlights panel')
|
||||
)
|
||||
|
||||
|
||||
def create_shortcut_map(custom_shortcuts):
|
||||
|
@ -427,6 +427,8 @@ class View:
|
||||
ui_operations.toggle_toc()
|
||||
elif data.name is 'toggle_bookmarks':
|
||||
ui_operations.toggle_bookmarks()
|
||||
elif data.name is 'toggle_highlights':
|
||||
ui_operations.toggle_highlights()
|
||||
elif data.name is 'new_bookmark':
|
||||
ui_operations.new_bookmark()
|
||||
elif data.name is 'toggle_inspector':
|
||||
|
@ -357,6 +357,8 @@ if window is window.top:
|
||||
to_python.toggle_toc()
|
||||
ui_operations.toggle_bookmarks = def():
|
||||
to_python.toggle_bookmarks()
|
||||
ui_operations.toggle_highlights = def():
|
||||
to_python.toggle_highlights()
|
||||
ui_operations.new_bookmark = def():
|
||||
to_python.new_bookmark()
|
||||
ui_operations.toggle_inspector = def():
|
||||
|
Loading…
x
Reference in New Issue
Block a user