Implement clicking on links in the preview panel

Clicking links in the preview panel now opens the linked to document in
an editor at the location pointed to by the link
This commit is contained in:
Kovid Goyal 2013-12-07 13:41:27 +05:30
parent 4491fad3d7
commit b8c52790bc
6 changed files with 68 additions and 6 deletions

Binary file not shown.

View File

@ -105,9 +105,26 @@ class PreviewIntegration
if this.in_split_mode
this.report_split(event.target)
else
window.py_bridge.request_sync(event.target.getAttribute("data-lnum"))
e = event.target
# Find the closest containing link, if any
lnum = e.getAttribute('data-lnum')
href = tn = ''
while e and e != document.body and e != document and (tn != 'a' or not href)
tn = e.tagName?.toLowerCase()
href = e.getAttribute('href')
e = e.parentNode
window.py_bridge.request_sync(tn, href, lnum)
return false
go_to_anchor: (anchor, lnum) =>
elem = document.getElementById(anchor)
if not elem
elem = document.querySelector('[name="' + anchor + '"]')
if elem
elem.scrollIntoView()
lnum = elem.getAttribute('data-lnum')
window.py_bridge.request_sync('', '', lnum)
window.calibre_preview_integration = new PreviewIntegration()
window.onload = window.calibre_preview_integration.onload

View File

@ -91,6 +91,7 @@ class Boss(QObject):
self.gui.preview.sync_requested.connect(self.sync_editor_to_preview)
self.gui.preview.split_start_requested.connect(self.split_start_requested)
self.gui.preview.split_requested.connect(self.split_requested)
self.gui.preview.link_clicked.connect(self.link_clicked)
def preferences(self):
p = Preferences(self.gui)
@ -668,6 +669,17 @@ class Boss(QObject):
self.apply_container_update_to_gui()
self.edit_file(bottom_name, 'html')
@in_thread_job
def link_clicked(self, name, anchor):
if name in editors:
editor = editors[name]
self.gui.central.show_editor(editor)
else:
syntax = syntax_from_mime(name, current_container().mime_map[name])
editor = self.edit_file(name, syntax)
if anchor:
editor.go_to_anchor(anchor)
@in_thread_job
def merge_requested(self, category, names, master):
self.commit_all_editors_to_container()

View File

@ -287,6 +287,20 @@ class TextEdit(QPlainTextEdit):
text = m.expand(template)
c.insertText(text)
return True
def go_to_anchor(self, anchor):
base = r'''%%s\s*=\s*['"]{0,1}%s''' % regex.escape(anchor)
raw = unicode(self.toPlainText())
m = regex.search(base % 'id', raw)
if m is None:
m = regex.search(base % 'name', raw)
if m is not None:
c = self.textCursor()
c.setPosition(m.start())
self.setTextCursor(c)
return True
return False
# }}}
# Line numbers and cursor line {{{

View File

@ -108,6 +108,9 @@ class Editor(QMainWindow):
def all_in_marked(self, *args, **kwargs):
return self.editor.all_in_marked(*args, **kwargs)
def go_to_anchor(self, *args, **kwargs):
return self.editor.go_to_anchor(*args, **kwargs)
# }}}
@property

View File

@ -14,6 +14,7 @@ from threading import Thread
from Queue import Queue, Empty
from collections import namedtuple
from functools import partial
from urlparse import urlparse
from PyQt4.Qt import (
QWidget, QVBoxLayout, QApplication, QSize, QNetworkAccessManager, QMenu, QIcon,
@ -273,7 +274,7 @@ def find_le(a, x):
class WebPage(QWebPage):
sync_requested = pyqtSignal(object)
sync_requested = pyqtSignal(object, object, object)
split_requested = pyqtSignal(object)
def __init__(self, parent):
@ -312,13 +313,17 @@ class WebPage(QWebPage):
mf.addToJavaScriptWindowObject("py_bridge", self)
mf.evaluateJavaScript(self.js)
@pyqtSlot(str)
def request_sync(self, lnum):
@pyqtSlot(str, str, str)
def request_sync(self, tag_name, href, lnum):
try:
self.sync_requested.emit(int(lnum))
self.sync_requested.emit(unicode(tag_name), unicode(href), int(unicode(lnum)))
except (TypeError, ValueError, OverflowError, AttributeError):
pass
def go_to_anchor(self, anchor, lnum):
self.mainFrame().evaluateJavaScript('window.calibre_preview_integration.go_to_anchor(%s, %s)' % (
json.dumps(anchor), json.dumps(str(lnum))))
@pyqtSlot(str)
def request_split(self, loc):
actions['split-in-preview'].setChecked(False)
@ -414,6 +419,7 @@ class Preview(QWidget):
sync_requested = pyqtSignal(object, object)
split_requested = pyqtSignal(object, object)
split_start_requested = pyqtSignal()
link_clicked = pyqtSignal(object, object)
def __init__(self, parent=None):
QWidget.__init__(self, parent)
@ -482,8 +488,18 @@ class Preview(QWidget):
self.view.findText(text, QWebPage.FindWrapsAroundDocument | (
QWebPage.FindBackward if direction == 'prev' else QWebPage.FindFlags(0)))
def request_sync(self, lnum):
def request_sync(self, tagname, href, lnum):
if self.current_name:
c = current_container()
if tagname == 'a' and href:
if href and href.startswith('#'):
name = self.current_name
else:
name = c.href_to_name(href, self.current_name) if href else None
if name == self.current_name:
return self.view.page().go_to_anchor(urlparse(href).fragment, lnum)
if name and c.exists(name) and c.mime_map[name] in OEB_DOCS:
return self.link_clicked.emit(name, urlparse(href).fragment)
self.sync_requested.emit(self.current_name, lnum)
def request_split(self, loc):