mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
E-book viewer: Show the URL when hovering over external links. Fixes #1911107 [Enhancement Request: ebook-viewer: Preview link destination](https://bugs.launchpad.net/calibre/+bug/1911107)
This commit is contained in:
parent
0139ed13fe
commit
943c830859
@ -496,6 +496,7 @@ class WebView(RestartingWebEngineView):
|
|||||||
self.show_home_page_on_ready = True
|
self.show_home_page_on_ready = True
|
||||||
self._size_hint = QSize(int(w/3), int(w/2))
|
self._size_hint = QSize(int(w/3), int(w/2))
|
||||||
self._page = WebPage(self)
|
self._page = WebPage(self)
|
||||||
|
self._page.linkHovered.connect(self.link_hovered)
|
||||||
self.view_is_ready = False
|
self.view_is_ready = False
|
||||||
self.bridge.bridge_ready.connect(self.on_bridge_ready)
|
self.bridge.bridge_ready.connect(self.on_bridge_ready)
|
||||||
self.bridge.view_created.connect(self.on_view_created)
|
self.bridge.view_created.connect(self.on_view_created)
|
||||||
@ -549,6 +550,11 @@ class WebView(RestartingWebEngineView):
|
|||||||
self.inspector = Inspector(parent.inspector_dock.toggleViewAction(), self)
|
self.inspector = Inspector(parent.inspector_dock.toggleViewAction(), self)
|
||||||
parent.inspector_dock.setWidget(self.inspector)
|
parent.inspector_dock.setWidget(self.inspector)
|
||||||
|
|
||||||
|
def link_hovered(self, url):
|
||||||
|
if url == 'javascript:void(0)':
|
||||||
|
url = ''
|
||||||
|
self.generic_action('show-status-message', {'text': url})
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
self.tts.shutdown()
|
self.tts.shutdown()
|
||||||
|
|
||||||
|
@ -165,13 +165,15 @@ def format_pos(progress_frac, length):
|
|||||||
return f'{pos:.1f} / {pages}'
|
return f'{pos:.1f} / {pages}'
|
||||||
|
|
||||||
|
|
||||||
def render_head_foot(div, which, region, metadata, current_toc_node, current_toc_toplevel_node, book_time, chapter_time, pos):
|
def render_head_foot(div, which, region, metadata, current_toc_node, current_toc_toplevel_node, book_time, chapter_time, pos, override):
|
||||||
template = get_session_data().get(which) or {}
|
template = get_session_data().get(which) or {}
|
||||||
field = template[region] or 'empty'
|
field = template[region] or 'empty'
|
||||||
interface_data = get_interface_data()
|
interface_data = get_interface_data()
|
||||||
text = ''
|
text = ''
|
||||||
has_clock = False
|
has_clock = False
|
||||||
if field is 'progress':
|
if override:
|
||||||
|
text = override
|
||||||
|
elif field is 'progress':
|
||||||
percent = min(100, max(Math.round(pos.progress_frac * 100), 0))
|
percent = min(100, max(Math.round(pos.progress_frac * 100), 0))
|
||||||
text = percent + '%'
|
text = percent + '%'
|
||||||
elif field is 'title':
|
elif field is 'title':
|
||||||
|
@ -209,6 +209,7 @@ class View:
|
|||||||
self.loaded_resources = {}
|
self.loaded_resources = {}
|
||||||
self.current_progress_frac = self.current_file_progress_frac = 0
|
self.current_progress_frac = self.current_file_progress_frac = 0
|
||||||
self.current_page_counts = {'current': 0, 'total': 0, 'pages_per_screen': 1}
|
self.current_page_counts = {'current': 0, 'total': 0, 'pages_per_screen': 1}
|
||||||
|
self.current_status_message = ''
|
||||||
self.current_toc_node = self.current_toc_toplevel_node = None
|
self.current_toc_node = self.current_toc_toplevel_node = None
|
||||||
self.current_toc_families = v'[]'
|
self.current_toc_families = v'[]'
|
||||||
self.report_cfi_callbacks = {}
|
self.report_cfi_callbacks = {}
|
||||||
@ -1244,26 +1245,35 @@ class View:
|
|||||||
}
|
}
|
||||||
return pos
|
return pos
|
||||||
|
|
||||||
|
def show_status_message(self, msg):
|
||||||
|
self.current_status_message = msg or ''
|
||||||
|
self.update_header_footer()
|
||||||
|
if self.current_status_message:
|
||||||
|
window.setTimeout(def(): self.show_status_message();, 10000)
|
||||||
|
|
||||||
def update_header_footer(self):
|
def update_header_footer(self):
|
||||||
sd = get_session_data()
|
sd = get_session_data()
|
||||||
has_clock = False
|
has_clock = False
|
||||||
pos = self.current_position_data
|
pos = self.current_position_data
|
||||||
|
if not self.book:
|
||||||
|
return
|
||||||
|
|
||||||
book_length = pos.book_length * max(0, 1 - pos.progress_frac)
|
book_length = pos.book_length * max(0, 1 - pos.progress_frac)
|
||||||
chapter_length = pos.chapter_length * max(0, 1 - pos.file_progress_frac)
|
chapter_length = pos.chapter_length * max(0, 1 - pos.file_progress_frac)
|
||||||
book_time = self.timers.time_for(book_length)
|
book_time = self.timers.time_for(book_length)
|
||||||
chapter_time = self.timers.time_for(chapter_length)
|
chapter_time = self.timers.time_for(chapter_length)
|
||||||
|
|
||||||
def render_template(div, sz_attr, name):
|
def render_template(div, edge, name):
|
||||||
nonlocal has_clock
|
nonlocal has_clock
|
||||||
c = div.lastChild
|
c = div.lastChild
|
||||||
b = c.previousSibling
|
b = c.previousSibling
|
||||||
a = b.previousSibling
|
a = b.previousSibling
|
||||||
if sd.get(sz_attr, 20) > 5:
|
if sd.get(f'margin_{edge}', 20) > 5:
|
||||||
mi = self.book.metadata
|
mi = self.book.metadata
|
||||||
hca = render_head_foot(a, name, 'left', mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos)
|
override = self.current_status_message if edge is 'bottom' else ''
|
||||||
hcb = render_head_foot(b, name, 'middle', mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos)
|
hca = render_head_foot(a, name, 'left', mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos, override)
|
||||||
hcc = render_head_foot(c, name, 'right', mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos)
|
hcb = render_head_foot(b, name, 'middle', mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos, '')
|
||||||
|
hcc = render_head_foot(c, name, 'right', mi, self.current_toc_node, self.current_toc_toplevel_node, book_time, chapter_time, pos, '')
|
||||||
if hca or hcb or hcc:
|
if hca or hcb or hcc:
|
||||||
has_clock = True
|
has_clock = True
|
||||||
else:
|
else:
|
||||||
@ -1273,7 +1283,7 @@ class View:
|
|||||||
div = document.getElementById(f'book-{edge}-margin')
|
div = document.getElementById(f'book-{edge}-margin')
|
||||||
if div:
|
if div:
|
||||||
tname = {'left':'left-margin', 'right': 'right-margin', 'top': 'header', 'bottom': 'footer'}[edge]
|
tname = {'left':'left-margin', 'right': 'right-margin', 'top': 'header', 'bottom': 'footer'}[edge]
|
||||||
render_template(div, f'margin_{edge}', tname)
|
render_template(div, edge, tname)
|
||||||
if has_clock:
|
if has_clock:
|
||||||
if not self.timer_ids.clock:
|
if not self.timer_ids.clock:
|
||||||
self.timer_ids.clock = window.setInterval(self.update_header_footer, 60000)
|
self.timer_ids.clock = window.setInterval(self.update_header_footer, 60000)
|
||||||
@ -1310,6 +1320,7 @@ class View:
|
|||||||
# We cannot encrypt this message because the resource data contains
|
# We cannot encrypt this message because the resource data contains
|
||||||
# Blob objects which do not survive encryption
|
# Blob objects which do not survive encryption
|
||||||
self.processing_spine_item_display = True
|
self.processing_spine_item_display = True
|
||||||
|
self.current_status_message = ''
|
||||||
self.iframe.style.visibility = 'hidden'
|
self.iframe.style.visibility = 'hidden'
|
||||||
self.iframe_wrapper.send_unencrypted_message('display',
|
self.iframe_wrapper.send_unencrypted_message('display',
|
||||||
resource_data=resource_data, book=self.book, name=self.currently_showing.name,
|
resource_data=resource_data, book=self.book, name=self.currently_showing.name,
|
||||||
|
@ -207,6 +207,8 @@ def highlight_action(uuid, which):
|
|||||||
def generic_action(which, data):
|
def generic_action(which, data):
|
||||||
if which is 'set-notes-in-highlight':
|
if which is 'set-notes-in-highlight':
|
||||||
view.set_notes_for_highlight(data.uuid, data.notes or '')
|
view.set_notes_for_highlight(data.uuid, data.notes or '')
|
||||||
|
if which is 'show-status-message':
|
||||||
|
view.show_status_message(data.text)
|
||||||
|
|
||||||
|
|
||||||
@from_python
|
@from_python
|
||||||
|
Loading…
x
Reference in New Issue
Block a user