mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Wire up the split in preview button (not yet implemented)
This commit is contained in:
parent
cf3d54c2d2
commit
9415af8e1e
@ -17,6 +17,21 @@ is_hidden = (elem) ->
|
|||||||
elem = elem.parentNode
|
elem = elem.parentNode
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
previous_sibling = (node) ->
|
||||||
|
node = node.previousSibling
|
||||||
|
while node and node.nodeType != Node.ELEMENT_NODE
|
||||||
|
node = node.previousSibling
|
||||||
|
return node
|
||||||
|
|
||||||
|
is_block = (elem) ->
|
||||||
|
style = window.getComputedStyle(elem)
|
||||||
|
return style.display in ['block', 'flex-box', 'box']
|
||||||
|
|
||||||
|
find_containing_block = (elem) ->
|
||||||
|
while elem and elem.getAttribute('data-is-block') != '1'
|
||||||
|
elem = elem.parentNode
|
||||||
|
return elem
|
||||||
|
|
||||||
class PreviewIntegration
|
class PreviewIntegration
|
||||||
|
|
||||||
###
|
###
|
||||||
@ -27,18 +42,20 @@ class PreviewIntegration
|
|||||||
constructor: () ->
|
constructor: () ->
|
||||||
if not this instanceof arguments.callee
|
if not this instanceof arguments.callee
|
||||||
throw new Error('PreviewIntegration constructor called as function')
|
throw new Error('PreviewIntegration constructor called as function')
|
||||||
|
this.blocks_found = false
|
||||||
|
this.in_split_mode = false
|
||||||
|
|
||||||
go_to_line: (lnum) ->
|
go_to_line: (lnum) =>
|
||||||
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
|
||||||
top = window.calibre_utils.abstop(node) - (window.innerHeight / 2)
|
top = window.calibre_utils.abstop(node) - (window.innerHeight / 2)
|
||||||
if (top < 0)
|
if top < 0
|
||||||
top = 0
|
top = 0
|
||||||
window.scrollTo(0, top)
|
window.scrollTo(0, top)
|
||||||
return
|
return
|
||||||
|
|
||||||
line_numbers: () ->
|
line_numbers: () =>
|
||||||
found_body = false
|
found_body = false
|
||||||
ans = []
|
ans = []
|
||||||
for node in document.getElementsByTagName('*')
|
for node in document.getElementsByTagName('*')
|
||||||
@ -49,18 +66,43 @@ class PreviewIntegration
|
|||||||
return ans
|
return ans
|
||||||
|
|
||||||
find_blocks: () =>
|
find_blocks: () =>
|
||||||
|
if this.blocks_found
|
||||||
|
return
|
||||||
for elem in document.body.getElementsByTagName('*')
|
for elem in document.body.getElementsByTagName('*')
|
||||||
style = window.getComputedStyle(elem)
|
if is_block(elem)
|
||||||
if style.display in ['block', 'flex-box', 'box']
|
|
||||||
elem.setAttribute('data-is-block', '1')
|
elem.setAttribute('data-is-block', '1')
|
||||||
elem.onclick = this.onclick
|
this.blocks_found = true
|
||||||
|
|
||||||
onload: () ->
|
split_mode: (enabled) =>
|
||||||
window.document.body.addEventListener('click', window.calibre_preview_integration.onclick, true)
|
this.in_split_mode = enabled
|
||||||
|
document.body.setAttribute('data-in-split-mode', if enabled then '1' else '0')
|
||||||
|
if enabled
|
||||||
|
this.find_blocks()
|
||||||
|
|
||||||
onclick: (event) ->
|
report_split: (node) =>
|
||||||
|
loc = []
|
||||||
|
parent = find_containing_block(node)
|
||||||
|
while parent and parent.tagName.toLowerCase() != 'body'
|
||||||
|
num = 0
|
||||||
|
sibling = previous_sibling(parent)
|
||||||
|
while sibling
|
||||||
|
num += 1
|
||||||
|
sibling = previous_sibling(sibling)
|
||||||
|
loc.push(num)
|
||||||
|
parent = parent.parentNode
|
||||||
|
loc.reverse()
|
||||||
|
window.py_bridge.request_split(loc)
|
||||||
|
|
||||||
|
onload: () =>
|
||||||
|
window.document.body.addEventListener('click', this.onclick, true)
|
||||||
|
|
||||||
|
onclick: (event) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
window.py_bridge.request_sync(event.target.getAttribute("data-lnum"))
|
if this.in_split_mode
|
||||||
|
this.report_split(event.target)
|
||||||
|
else
|
||||||
|
window.py_bridge.request_sync(event.target.getAttribute("data-lnum"))
|
||||||
|
return false
|
||||||
|
|
||||||
window.calibre_preview_integration = new PreviewIntegration()
|
window.calibre_preview_integration = new PreviewIntegration()
|
||||||
window.onload = window.calibre_preview_integration.onload
|
window.onload = window.calibre_preview_integration.onload
|
||||||
|
@ -57,6 +57,7 @@ class Boss(QObject):
|
|||||||
self.gui.central.close_requested.connect(self.editor_close_requested)
|
self.gui.central.close_requested.connect(self.editor_close_requested)
|
||||||
self.gui.central.search_panel.search_triggered.connect(self.search)
|
self.gui.central.search_panel.search_triggered.connect(self.search)
|
||||||
self.gui.preview.sync_requested.connect(self.sync_editor_to_preview)
|
self.gui.preview.sync_requested.connect(self.sync_editor_to_preview)
|
||||||
|
self.gui.preview.split_start_requested.connect(self.split_start_requested)
|
||||||
|
|
||||||
def mkdtemp(self, prefix=''):
|
def mkdtemp(self, prefix=''):
|
||||||
self.container_count += 1
|
self.container_count += 1
|
||||||
@ -502,6 +503,11 @@ class Boss(QObject):
|
|||||||
if ok:
|
if ok:
|
||||||
ed.current_line = num
|
ed.current_line = num
|
||||||
|
|
||||||
|
def split_start_requested(self):
|
||||||
|
if not self.check_dirtied():
|
||||||
|
return self.gui.preview.stop_split()
|
||||||
|
self.gui.preview.do_start_split()
|
||||||
|
|
||||||
def sync_editor_to_preview(self, name, lnum):
|
def sync_editor_to_preview(self, name, lnum):
|
||||||
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
|
||||||
|
@ -6,8 +6,9 @@ from __future__ import (unicode_literals, division, absolute_import,
|
|||||||
__license__ = 'GPL v3'
|
__license__ = 'GPL v3'
|
||||||
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
|
||||||
import time
|
import time, textwrap
|
||||||
from bisect import bisect_right
|
from bisect import bisect_right
|
||||||
|
from base64 import b64encode
|
||||||
from future_builtins import map
|
from future_builtins import map
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from Queue import Queue, Empty
|
from Queue import Queue, Empty
|
||||||
@ -23,6 +24,7 @@ from calibre.constants import iswindows, DEBUG
|
|||||||
from calibre.ebooks.oeb.polish.parsing import parse
|
from calibre.ebooks.oeb.polish.parsing import parse
|
||||||
from calibre.ebooks.oeb.base import serialize, OEB_DOCS
|
from calibre.ebooks.oeb.base import serialize, OEB_DOCS
|
||||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
from calibre.ptempfile import PersistentTemporaryDirectory
|
||||||
|
from calibre.gui2 import error_dialog
|
||||||
from calibre.gui2.tweak_book import current_container, editors, tprefs, actions
|
from calibre.gui2.tweak_book import current_container, editors, tprefs, actions
|
||||||
from calibre.gui2.viewer.documentview import apply_settings
|
from calibre.gui2.viewer.documentview import apply_settings
|
||||||
from calibre.gui2.viewer.config import config
|
from calibre.gui2.viewer.config import config
|
||||||
@ -237,6 +239,7 @@ def find_le(a, x):
|
|||||||
class WebPage(QWebPage):
|
class WebPage(QWebPage):
|
||||||
|
|
||||||
sync_requested = pyqtSignal(object)
|
sync_requested = pyqtSignal(object)
|
||||||
|
split_requested = pyqtSignal(object)
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QWebPage.__init__(self, parent)
|
QWebPage.__init__(self, parent)
|
||||||
@ -251,6 +254,10 @@ class WebPage(QWebPage):
|
|||||||
settings.setAttribute(settings.LinksIncludedInFocusChain, False)
|
settings.setAttribute(settings.LinksIncludedInFocusChain, False)
|
||||||
settings.setAttribute(settings.DeveloperExtrasEnabled, True)
|
settings.setAttribute(settings.DeveloperExtrasEnabled, True)
|
||||||
settings.setDefaultTextEncoding('utf-8')
|
settings.setDefaultTextEncoding('utf-8')
|
||||||
|
data = 'data:text/css;charset=utf-8;base64,'
|
||||||
|
css = '[data-in-split-mode="1"] [data-is-block="1"]:hover { cursor: pointer !important; border-top: solid 5px green !important }'
|
||||||
|
data += b64encode(css.encode('utf-8'))
|
||||||
|
settings.setUserStyleSheetUrl(QUrl(data))
|
||||||
|
|
||||||
self.setNetworkAccessManager(NetworkAccessManager(self))
|
self.setNetworkAccessManager(NetworkAccessManager(self))
|
||||||
self.setLinkDelegationPolicy(self.DelegateAllLinks)
|
self.setLinkDelegationPolicy(self.DelegateAllLinks)
|
||||||
@ -277,6 +284,14 @@ class WebPage(QWebPage):
|
|||||||
except (TypeError, ValueError, OverflowError, AttributeError):
|
except (TypeError, ValueError, OverflowError, AttributeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@pyqtSlot('QList<int>')
|
||||||
|
def request_split(self, loc):
|
||||||
|
actions['split-in-preview'].setChecked(False)
|
||||||
|
if not loc:
|
||||||
|
return error_dialog(self.view(), _('Invalid location'),
|
||||||
|
_('Cannot split on the body tag'), show=True)
|
||||||
|
self.split_requested.emit(loc)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def line_numbers(self):
|
def line_numbers(self):
|
||||||
if self._line_numbers is None:
|
if self._line_numbers is None:
|
||||||
@ -297,6 +312,12 @@ 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 split_mode(self, enabled):
|
||||||
|
self.mainFrame().evaluateJavaScript(
|
||||||
|
'window.calibre_preview_integration.split_mode(%s)' % (
|
||||||
|
'true' if enabled else 'false'))
|
||||||
|
|
||||||
|
|
||||||
class WebView(QWebView):
|
class WebView(QWebView):
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@ -343,6 +364,8 @@ class WebView(QWebView):
|
|||||||
class Preview(QWidget):
|
class Preview(QWidget):
|
||||||
|
|
||||||
sync_requested = pyqtSignal(object, object)
|
sync_requested = pyqtSignal(object, object)
|
||||||
|
split_requested = pyqtSignal(object, object)
|
||||||
|
split_start_requested = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QWidget.__init__(self, parent)
|
QWidget.__init__(self, parent)
|
||||||
@ -351,6 +374,8 @@ class Preview(QWidget):
|
|||||||
l.setContentsMargins(0, 0, 0, 0)
|
l.setContentsMargins(0, 0, 0, 0)
|
||||||
self.view = WebView(self)
|
self.view = WebView(self)
|
||||||
self.view.page().sync_requested.connect(self.request_sync)
|
self.view.page().sync_requested.connect(self.request_sync)
|
||||||
|
self.view.page().split_requested.connect(self.request_split)
|
||||||
|
self.view.page().loadFinished.connect(self.load_finished)
|
||||||
self.inspector = self.view.inspector
|
self.inspector = self.view.inspector
|
||||||
self.inspector.setPage(self.view.page())
|
self.inspector.setPage(self.view.page())
|
||||||
l.addWidget(self.view)
|
l.addWidget(self.view)
|
||||||
@ -373,6 +398,13 @@ class Preview(QWidget):
|
|||||||
|
|
||||||
self.bar.addSeparator()
|
self.bar.addSeparator()
|
||||||
|
|
||||||
|
ac = actions['split-in-preview']
|
||||||
|
ac.setCheckable(True)
|
||||||
|
ac.setChecked(False)
|
||||||
|
ac.toggled.connect(self.split_toggled)
|
||||||
|
self.split_toggled(ac.isChecked())
|
||||||
|
self.bar.addAction(ac)
|
||||||
|
|
||||||
ac = actions['reload-preview']
|
ac = actions['reload-preview']
|
||||||
ac.triggered.connect(self.refresh)
|
ac.triggered.connect(self.refresh)
|
||||||
self.bar.addAction(ac)
|
self.bar.addAction(ac)
|
||||||
@ -390,6 +422,10 @@ class Preview(QWidget):
|
|||||||
if self.current_name:
|
if self.current_name:
|
||||||
self.sync_requested.emit(self.current_name, lnum)
|
self.sync_requested.emit(self.current_name, lnum)
|
||||||
|
|
||||||
|
def request_split(self, loc):
|
||||||
|
if self.current_name:
|
||||||
|
self.split_requested.emit(self.current_name, loc)
|
||||||
|
|
||||||
def sync_to_editor(self, name, lnum):
|
def sync_to_editor(self, name, lnum):
|
||||||
self.current_sync_request = (name, lnum)
|
self.current_sync_request = (name, lnum)
|
||||||
QTimer.singleShot(100, self._sync_to_editor)
|
QTimer.singleShot(100, self._sync_to_editor)
|
||||||
@ -455,3 +491,26 @@ class Preview(QWidget):
|
|||||||
if is_visible:
|
if is_visible:
|
||||||
self.refresh()
|
self.refresh()
|
||||||
|
|
||||||
|
def split_toggled(self, checked):
|
||||||
|
actions['split-in-preview'].setToolTip(textwrap.fill(_(
|
||||||
|
'Abort file split') if checked else _(
|
||||||
|
'Split this file at a specified location.\n\nAfter clicking this button, click'
|
||||||
|
' inside the preview panel above at the location you want the file to be split.')))
|
||||||
|
if checked:
|
||||||
|
self.split_start_requested.emit()
|
||||||
|
else:
|
||||||
|
self.view.page().split_mode(False)
|
||||||
|
|
||||||
|
def do_start_split(self):
|
||||||
|
self.view.page().split_mode(True)
|
||||||
|
|
||||||
|
def stop_split(self):
|
||||||
|
actions['split-in-preview'].setChecked(False)
|
||||||
|
|
||||||
|
def load_finished(self, ok):
|
||||||
|
if actions['split-in-preview'].isChecked():
|
||||||
|
if ok:
|
||||||
|
self.do_start_split()
|
||||||
|
else:
|
||||||
|
self.stop_split()
|
||||||
|
|
||||||
|
@ -223,6 +223,8 @@ class Main(MainWindow):
|
|||||||
self.action_auto_sync_preview = reg('sync-right.png', _('Sync preview position to editor position'), None, 'sync-preview-to-editor', (), _(
|
self.action_auto_sync_preview = reg('sync-right.png', _('Sync preview position to editor position'), None, 'sync-preview-to-editor', (), _(
|
||||||
'Sync preview position to editor position'))
|
'Sync preview position to editor position'))
|
||||||
self.action_reload_preview = reg('view-refresh.png', _('Refresh preview'), None, 'reload-preview', ('F5',), _('Refresh preview'))
|
self.action_reload_preview = reg('view-refresh.png', _('Refresh preview'), None, 'reload-preview', ('F5',), _('Refresh preview'))
|
||||||
|
self.action_split_in_preview = reg('auto_author_sort.png', _('Split this file'), None, 'split-in-preview', (), _(
|
||||||
|
'Split file in the preview panel'))
|
||||||
|
|
||||||
# Search actions
|
# Search actions
|
||||||
group = _('Search')
|
group = _('Search')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user