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
|
# selection
|
||||||
this.scroll_to_xpos(left+5)
|
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
|
# Jump to the position indicated by the specified conformal fragment
|
||||||
# indicator (requires the cfi.coffee library). When in paged mode, the
|
# indicator (requires the cfi.coffee library). When in paged mode, the
|
||||||
# scroll is performed so that the column containing the position
|
# scroll is performed so that the column containing the position
|
||||||
@ -540,6 +540,8 @@ class PagedDisplay
|
|||||||
this.scroll_to_xpos(x)
|
this.scroll_to_xpos(x)
|
||||||
else
|
else
|
||||||
window.scrollTo(0, y)
|
window.scrollTo(0, y)
|
||||||
|
if window.py_bridge
|
||||||
|
window.py_bridge.jump_to_cfi_finished(job_id)
|
||||||
)
|
)
|
||||||
|
|
||||||
current_cfi: () ->
|
current_cfi: () ->
|
||||||
|
@ -93,6 +93,7 @@ class Document(QWebPage): # {{{
|
|||||||
# javascript, get/set the value as: py_bridge.value
|
# javascript, get/set the value as: py_bridge.value
|
||||||
self.bridge_value = None
|
self.bridge_value = None
|
||||||
self.first_load = True
|
self.first_load = True
|
||||||
|
self.jump_to_cfi_listeners = set()
|
||||||
|
|
||||||
self.debug_javascript = debug_javascript
|
self.debug_javascript = debug_javascript
|
||||||
self.anchor_positions = {}
|
self.anchor_positions = {}
|
||||||
@ -336,6 +337,11 @@ class Document(QWebPage): # {{{
|
|||||||
def debug(self, msg):
|
def debug(self, msg):
|
||||||
prints(unicode(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):
|
def reference_mode(self, enable):
|
||||||
self.javascript(('enter' if enable else 'leave')+'_reference_mode()')
|
self.javascript(('enter' if enable else 'leave')+'_reference_mode()')
|
||||||
|
|
||||||
|
@ -722,23 +722,16 @@ class EbookViewer(MainWindow):
|
|||||||
if self.isFullScreen():
|
if self.isFullScreen():
|
||||||
self.relayout_fullscreen_labels()
|
self.relayout_fullscreen_labels()
|
||||||
self.view.document.after_resize()
|
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:
|
if not wmc:
|
||||||
pre_footnote_pos = self.pre_footnote_toggle_position()
|
pre_footnote_pos = self.pre_footnote_toggle_position()
|
||||||
if pre_footnote_pos is not None:
|
if pre_footnote_pos is not None:
|
||||||
self.view.document.page_number = pre_footnote_pos
|
self.view.document.page_number = pre_footnote_pos
|
||||||
else:
|
else:
|
||||||
self.view.document.page_position.restore()
|
self.view.document.page_position.restore()
|
||||||
|
self.update_page_number()
|
||||||
def scroll_after_resize_done(self):
|
if len(self.page_position_on_footnote_toggle) % 2 == 1:
|
||||||
self.update_page_number()
|
self.page_position_on_footnote_toggle[-1] = self.page_position_on_footnote_toggle[-1]._replace(
|
||||||
if len(self.page_position_on_footnote_toggle) % 2 == 1:
|
after_resize_page_number=self.view.document.page_number)
|
||||||
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):
|
def update_page_number(self):
|
||||||
self.set_page_number(self.view.document.scroll_fraction)
|
self.set_page_number(self.view.document.scroll_fraction)
|
||||||
|
@ -7,12 +7,19 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2012, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
import json
|
import json, time
|
||||||
|
|
||||||
|
from PyQt5.Qt import QApplication, QEventLoop
|
||||||
|
|
||||||
|
from calibre.constants import DEBUG
|
||||||
|
|
||||||
class PagePosition(object):
|
class PagePosition(object):
|
||||||
|
|
||||||
def __init__(self, document):
|
def __init__(self, document):
|
||||||
self.document = document
|
self.document = document
|
||||||
|
document.jump_to_cfi_listeners.add(self)
|
||||||
|
self.cfi_job_id = 0
|
||||||
|
self.pending_scrolls = set()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def viewport_cfi(self):
|
def viewport_cfi(self):
|
||||||
@ -30,9 +37,22 @@ class PagePosition(object):
|
|||||||
|
|
||||||
def scroll_to_cfi(self, cfi):
|
def scroll_to_cfi(self, cfi):
|
||||||
if cfi:
|
if cfi:
|
||||||
|
jid = self.cfi_job_id
|
||||||
|
self.cfi_job_id += 1
|
||||||
cfi = json.dumps(cfi)
|
cfi = json.dumps(cfi)
|
||||||
|
self.pending_scrolls.add(jid)
|
||||||
self.document.mainFrame().evaluateJavaScript(
|
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
|
@property
|
||||||
def current_pos(self):
|
def current_pos(self):
|
||||||
@ -47,6 +67,9 @@ class PagePosition(object):
|
|||||||
def __exit__(self, *args):
|
def __exit__(self, *args):
|
||||||
self.restore()
|
self.restore()
|
||||||
|
|
||||||
|
def __call__(self, cfi_job_id):
|
||||||
|
self.pending_scrolls.discard(cfi_job_id)
|
||||||
|
|
||||||
def save(self, overwrite=True):
|
def save(self, overwrite=True):
|
||||||
if not overwrite and self._cpos is not None:
|
if not overwrite and self._cpos is not None:
|
||||||
return
|
return
|
||||||
@ -66,5 +89,3 @@ class PagePosition(object):
|
|||||||
|
|
||||||
def set_pos(self, pos):
|
def set_pos(self, pos):
|
||||||
self._cpos = pos
|
self._cpos = pos
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user