Preview panel: Allow syncing of position more accurately when there are multiple tags on the same source code line

This commit is contained in:
Kovid Goyal 2014-05-25 14:29:25 +05:30
parent 70a1748deb
commit f8e8d9caa0
4 changed files with 33 additions and 16 deletions

Binary file not shown.

View File

@ -226,6 +226,11 @@ get_matched_css = (node, is_ancestor, all_properties) ->
return ans.reverse() return ans.reverse()
scroll_to_node = (node) ->
if node is document.body
window.scrollTo(0, 0)
else
node.scrollIntoView()
class PreviewIntegration class PreviewIntegration
@ -244,11 +249,15 @@ class PreviewIntegration
for node in document.querySelectorAll('[data-lnum="' + lnum + '"]') for node in document.querySelectorAll('[data-lnum="' + lnum + '"]')
if is_hidden(node) if is_hidden(node)
continue continue
if node is document.body scroll_to_node(node)
window.scrollTo(0, 0)
else go_to_sourceline_address: (sourceline, tags) =>
node.scrollIntoView() for node, index in document.querySelectorAll('[data-lnum="' + sourceline + '"]')
return if index >= tags.length or node.tagName.toLowerCase() != tags[index]
break
if index == tags.length - 1 and not is_hidden(node)
return scroll_to_node(node)
this.go_to_line(sourceline)
line_numbers: () => line_numbers: () =>
found_body = false found_body = false
@ -300,14 +309,14 @@ class PreviewIntegration
this.report_split(event.target) this.report_split(event.target)
else else
e = event.target e = event.target
address = get_sourceline_address(e)
# Find the closest containing link, if any # Find the closest containing link, if any
lnum = e.getAttribute('data-lnum')
href = tn = '' href = tn = ''
while e and e != document.body and e != document and (tn != 'a' or not href) while e and e != document.body and e != document and (tn != 'a' or not href)
tn = e.tagName?.toLowerCase() tn = e.tagName?.toLowerCase()
href = e.getAttribute('href') href = e.getAttribute('href')
e = e.parentNode e = e.parentNode
window.py_bridge.request_sync(tn, href, lnum) window.py_bridge.request_sync(tn, href, JSON.stringify(address))
return false return false
go_to_anchor: (anchor, lnum) => go_to_anchor: (anchor, lnum) =>

View File

@ -1014,11 +1014,11 @@ class Boss(QObject):
mt = current_container().mime_map.get(name, guess_type(name)) mt = current_container().mime_map.get(name, guess_type(name))
self.edit_file_requested(name, None, mt) self.edit_file_requested(name, None, mt)
def sync_editor_to_preview(self, name, lnum): def sync_editor_to_preview(self, name, sourceline_address):
editor = self.edit_file(name, 'html') editor = self.edit_file(name, 'html')
self.ignore_preview_to_editor_sync = True self.ignore_preview_to_editor_sync = True
try: try:
editor.current_line = lnum editor.goto_sourceline(*sourceline_address)
finally: finally:
self.ignore_preview_to_editor_sync = False self.ignore_preview_to_editor_sync = False
@ -1029,7 +1029,7 @@ class Boss(QObject):
if ed is not None: if ed is not None:
name = editor_name(ed) name = editor_name(ed)
if name is not None and getattr(ed, 'syntax', None) == 'html': if name is not None and getattr(ed, 'syntax', None) == 'html':
self.gui.preview.sync_to_editor(name, ed.current_line) self.gui.preview.sync_to_editor(name, ed.current_tag())
def sync_live_css_to_editor(self): def sync_live_css_to_editor(self):
ed = self.gui.central.current_editor ed = self.gui.central.current_editor

View File

@ -330,9 +330,9 @@ class WebPage(QWebPage):
mf.evaluateJavaScript(self.js) mf.evaluateJavaScript(self.js)
@pyqtSlot(str, str, str) @pyqtSlot(str, str, str)
def request_sync(self, tag_name, href, lnum): def request_sync(self, tag_name, href, sourceline_address):
try: try:
self.sync_requested.emit(unicode(tag_name), unicode(href), int(unicode(lnum))) self.sync_requested.emit(unicode(tag_name), unicode(href), json.loads(unicode(sourceline_address)))
except (TypeError, ValueError, OverflowError, AttributeError): except (TypeError, ValueError, OverflowError, AttributeError):
pass pass
@ -369,6 +369,14 @@ class WebPage(QWebPage):
self.mainFrame().evaluateJavaScript( self.mainFrame().evaluateJavaScript(
'window.calibre_preview_integration.go_to_line(%d)' % lnum) 'window.calibre_preview_integration.go_to_line(%d)' % lnum)
def go_to_sourceline_address(self, sourceline_address):
lnum, tags = sourceline_address
if lnum is None:
return
tags = [x.lower() for x in tags]
self.mainFrame().evaluateJavaScript(
'window.calibre_preview_integration.go_to_sourceline_address(%d, %s)' % (lnum, json.dumps(tags)))
def split_mode(self, enabled): def split_mode(self, enabled):
self.mainFrame().evaluateJavaScript( self.mainFrame().evaluateJavaScript(
'window.calibre_preview_integration.split_mode(%s)' % ( 'window.calibre_preview_integration.split_mode(%s)' % (
@ -538,8 +546,8 @@ class Preview(QWidget):
if self.current_name: if self.current_name:
self.split_requested.emit(self.current_name, loc, totals) self.split_requested.emit(self.current_name, loc, totals)
def sync_to_editor(self, name, lnum): def sync_to_editor(self, name, sourceline_address):
self.current_sync_request = (name, lnum) self.current_sync_request = (name, sourceline_address)
QTimer.singleShot(100, self._sync_to_editor) QTimer.singleShot(100, self._sync_to_editor)
def _sync_to_editor(self): def _sync_to_editor(self):
@ -550,9 +558,9 @@ class Preview(QWidget):
return QTimer.singleShot(100, self._sync_to_editor) return QTimer.singleShot(100, self._sync_to_editor)
except TypeError: except TypeError:
return # Happens if current_sync_request is None return # Happens if current_sync_request is None
lnum = self.current_sync_request[1] sourceline_address = self.current_sync_request[1]
self.current_sync_request = None self.current_sync_request = None
self.view.page().go_to_line(lnum) self.view.page().go_to_sourceline_address(sourceline_address)
def show(self, name): def show(self, name):
if name != self.current_name: if name != self.current_name: