From 195ff72d4473bf6998309a335b5872951ea7006b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 7 Jul 2020 21:49:44 +0530 Subject: [PATCH] Edit book: Fix initial sync of preview panel to cursor position sometimes not working when a new HTML file is opened for editing --- src/calibre/gui2/tweak_book/boss.py | 8 ++++++-- .../gui2/tweak_book/editor/syntax/base.py | 4 ++++ src/calibre/gui2/tweak_book/editor/widget.py | 4 ++++ src/calibre/gui2/tweak_book/preview.py | 17 +++++++++++------ 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/calibre/gui2/tweak_book/boss.py b/src/calibre/gui2/tweak_book/boss.py index 2041684bf1..b933e6542c 100644 --- a/src/calibre/gui2/tweak_book/boss.py +++ b/src/calibre/gui2/tweak_book/boss.py @@ -12,7 +12,7 @@ from functools import partial, wraps from PyQt5.Qt import ( QApplication, QCheckBox, QDialog, QDialogButtonBox, QGridLayout, QIcon, - QInputDialog, QLabel, QMimeData, QObject, QSize, Qt, QUrl, QVBoxLayout, + QInputDialog, QLabel, QMimeData, QObject, QSize, Qt, QTimer, QUrl, QVBoxLayout, pyqtSignal ) @@ -1497,7 +1497,11 @@ class Boss(QObject): if ed is not None: name = editor_name(ed) if name is not None and getattr(ed, 'syntax', None) == 'html': - self.gui.preview.sync_to_editor(name, ed.current_tag()) + ct = ed.current_tag() + self.gui.preview.sync_to_editor(name, ct) + hl = getattr(ed, 'highlighter', None) + if hl is not None and hl.is_working: + QTimer.singleShot(75, self.sync_preview_to_editor) def show_partial_cfi_in_editor(self, name, cfi): editor = self.edit_file(name, 'html') diff --git a/src/calibre/gui2/tweak_book/editor/syntax/base.py b/src/calibre/gui2/tweak_book/editor/syntax/base.py index 538bd4d726..12d7a8d291 100644 --- a/src/calibre/gui2/tweak_book/editor/syntax/base.py +++ b/src/calibre/gui2/tweak_book/editor/syntax/base.py @@ -201,6 +201,10 @@ class SyntaxHighlighter(object): finally: self.ignore_requests = False + @property + def is_working(self): + return bool(self.requests) + def parse_single_block(self, block): ud, is_new_ud = self.get_user_data(block) orig_state = ud.state diff --git a/src/calibre/gui2/tweak_book/editor/widget.py b/src/calibre/gui2/tweak_book/editor/widget.py index 11509790c5..1b5999c03a 100644 --- a/src/calibre/gui2/tweak_book/editor/widget.py +++ b/src/calibre/gui2/tweak_book/editor/widget.py @@ -182,6 +182,10 @@ class Editor(QMainWindow): def current_tag(self, for_position_sync=True): return self.editor.current_tag(for_position_sync=for_position_sync) + @property + def highlighter(self): + return self.editor.highlighter + @property def number_of_lines(self): return self.editor.blockCount() diff --git a/src/calibre/gui2/tweak_book/preview.py b/src/calibre/gui2/tweak_book/preview.py index 0ecb330d03..e6804113ef 100644 --- a/src/calibre/gui2/tweak_book/preview.py +++ b/src/calibre/gui2/tweak_book/preview.py @@ -438,6 +438,7 @@ class Preview(QWidget): self.l = l = QVBoxLayout() self.setLayout(l) l.setContentsMargins(0, 0, 0, 0) + self.current_sync_retry_count = 0 self.view = WebView(self) self.view._page.bridge.request_sync.connect(self.request_sync) self.view._page.bridge.request_split.connect(self.request_split) @@ -533,20 +534,24 @@ class Preview(QWidget): if self.current_name: self.split_requested.emit(self.current_name, loc, totals) + @property + def bridge_ready(self): + return self.view._page.bridge.ready + def sync_to_editor(self, name, sourceline_address): self.current_sync_request = (name, sourceline_address) + self.current_sync_retry_count = 0 QTimer.singleShot(100, self._sync_to_editor) def _sync_to_editor(self): - if not actions['sync-preview-to-editor'].isChecked(): + if not actions['sync-preview-to-editor'].isChecked() or self.current_sync_retry_count >= 3000 or self.current_sync_request is None: return - try: - if self.refresh_timer.isActive() or self.current_sync_request[0] != self.current_name: - return QTimer.singleShot(100, self._sync_to_editor) - except TypeError: - return # Happens if current_sync_request is None + if self.refresh_timer.isActive() or not self.bridge_ready or self.current_sync_request[0] != self.current_name: + self.current_sync_retry_count += 1 + return QTimer.singleShot(100, self._sync_to_editor) sourceline_address = self.current_sync_request[1] self.current_sync_request = None + self.current_sync_retry_count = 0 self.view._page.go_to_sourceline_address(sourceline_address) def report_worker_launch_error(self):