mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Make jumping to a cfi pseudo synchronous by spinning the event loop while waiting for the scroll to finish
This commit is contained in:
parent
c9a0f23173
commit
bdf4e01d7a
Binary file not shown.
@ -530,7 +530,7 @@ class PagedDisplay
|
||||
# selection
|
||||
this.scroll_to_xpos(left+5)
|
||||
|
||||
jump_to_cfi: (cfi) ->
|
||||
jump_to_cfi: (cfi, job_id=-1) ->
|
||||
# Jump to the position indicated by the specified conformal fragment
|
||||
# indicator (requires the cfi.coffee library). When in paged mode, the
|
||||
# scroll is performed so that the column containing the position
|
||||
@ -540,6 +540,8 @@ class PagedDisplay
|
||||
this.scroll_to_xpos(x)
|
||||
else
|
||||
window.scrollTo(0, y)
|
||||
if window.py_bridge
|
||||
window.py_bridge.jump_to_cfi_finished(job_id)
|
||||
)
|
||||
|
||||
current_cfi: () ->
|
||||
|
@ -93,6 +93,7 @@ class Document(QWebPage): # {{{
|
||||
# javascript, get/set the value as: py_bridge.value
|
||||
self.bridge_value = None
|
||||
self.first_load = True
|
||||
self.jump_to_cfi_listeners = set()
|
||||
|
||||
self.debug_javascript = debug_javascript
|
||||
self.anchor_positions = {}
|
||||
@ -336,6 +337,11 @@ class Document(QWebPage): # {{{
|
||||
def debug(self, msg):
|
||||
prints(unicode(msg))
|
||||
|
||||
@pyqtSlot(int)
|
||||
def jump_to_cfi_finished(self, job_id):
|
||||
for l in self.jump_to_cfi_listeners:
|
||||
l(job_id)
|
||||
|
||||
def reference_mode(self, enable):
|
||||
self.javascript(('enter' if enable else 'leave')+'_reference_mode()')
|
||||
|
||||
|
@ -722,23 +722,16 @@ class EbookViewer(MainWindow):
|
||||
if self.isFullScreen():
|
||||
self.relayout_fullscreen_labels()
|
||||
self.view.document.after_resize()
|
||||
# For some reason scroll_fraction returns incorrect results in paged
|
||||
# mode for some time after a resize is finished. No way of knowing
|
||||
# exactly how long, so we update it in a second, in the hopes that it
|
||||
# will be enough *most* of the time.
|
||||
QTimer.singleShot(1000, self.scroll_after_resize_done)
|
||||
if not wmc:
|
||||
pre_footnote_pos = self.pre_footnote_toggle_position()
|
||||
if pre_footnote_pos is not None:
|
||||
self.view.document.page_number = pre_footnote_pos
|
||||
else:
|
||||
self.view.document.page_position.restore()
|
||||
|
||||
def scroll_after_resize_done(self):
|
||||
self.update_page_number()
|
||||
if len(self.page_position_on_footnote_toggle) % 2 == 1:
|
||||
self.page_position_on_footnote_toggle[-1] = self.page_position_on_footnote_toggle[-1]._replace(
|
||||
after_resize_page_number=self.view.document.page_number)
|
||||
self.update_page_number()
|
||||
if len(self.page_position_on_footnote_toggle) % 2 == 1:
|
||||
self.page_position_on_footnote_toggle[-1] = self.page_position_on_footnote_toggle[-1]._replace(
|
||||
after_resize_page_number=self.view.document.page_number)
|
||||
|
||||
def update_page_number(self):
|
||||
self.set_page_number(self.view.document.scroll_fraction)
|
||||
|
@ -7,12 +7,19 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import json
|
||||
import json, time
|
||||
|
||||
from PyQt5.Qt import QApplication, QEventLoop
|
||||
|
||||
from calibre.constants import DEBUG
|
||||
|
||||
class PagePosition(object):
|
||||
|
||||
def __init__(self, document):
|
||||
self.document = document
|
||||
document.jump_to_cfi_listeners.add(self)
|
||||
self.cfi_job_id = 0
|
||||
self.pending_scrolls = set()
|
||||
|
||||
@property
|
||||
def viewport_cfi(self):
|
||||
@ -30,9 +37,22 @@ class PagePosition(object):
|
||||
|
||||
def scroll_to_cfi(self, cfi):
|
||||
if cfi:
|
||||
jid = self.cfi_job_id
|
||||
self.cfi_job_id += 1
|
||||
cfi = json.dumps(cfi)
|
||||
self.pending_scrolls.add(jid)
|
||||
self.document.mainFrame().evaluateJavaScript(
|
||||
'paged_display.jump_to_cfi(%s)'%cfi)
|
||||
'paged_display.jump_to_cfi(%s, %d)' % (cfi, jid))
|
||||
# jump_to_cfi is async, so we wait for it to complete
|
||||
st = time.time()
|
||||
WAIT = 1 # seconds
|
||||
while jid in self.pending_scrolls and time.time() - st < WAIT:
|
||||
QApplication.processEvents(QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers)
|
||||
time.sleep(0.01)
|
||||
if jid in self.pending_scrolls:
|
||||
self.pending_scrolls.discard(jid)
|
||||
if DEBUG:
|
||||
print ('jump_to_cfi() failed to complete after %s seconds' % WAIT)
|
||||
|
||||
@property
|
||||
def current_pos(self):
|
||||
@ -47,6 +67,9 @@ class PagePosition(object):
|
||||
def __exit__(self, *args):
|
||||
self.restore()
|
||||
|
||||
def __call__(self, cfi_job_id):
|
||||
self.pending_scrolls.discard(cfi_job_id)
|
||||
|
||||
def save(self, overwrite=True):
|
||||
if not overwrite and self._cpos is not None:
|
||||
return
|
||||
@ -66,5 +89,3 @@ class PagePosition(object):
|
||||
|
||||
def set_pos(self, pos):
|
||||
self._cpos = pos
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user