Implement #2829 (Request for hyphenation)

This commit is contained in:
Kovid Goyal 2009-07-14 18:12:29 -06:00
parent ffb1d3d770
commit ed92482019
7 changed files with 127 additions and 11 deletions

View File

@ -146,6 +146,9 @@ class EbookIterator(object):
self.opf = OPF(self.pathtoopf, os.path.dirname(self.pathtoopf)) self.opf = OPF(self.pathtoopf, os.path.dirname(self.pathtoopf))
self.language = self.opf.language
if self.language:
self.language = self.language.lower()
self.spine = [SpineItem(i.path) for i in self.opf.spine] self.spine = [SpineItem(i.path) for i in self.opf.spine]
cover = self.opf.cover cover = self.opf.cover

View File

@ -19,7 +19,7 @@ class PluginWidget(Widget, Ui_Form):
def __init__(self, parent, get_option, get_help, db=None, book_id=None): def __init__(self, parent, get_option, get_help, db=None, book_id=None):
Widget.__init__(self, parent, 'mobi_output', Widget.__init__(self, parent, 'mobi_output',
['prefer_author_sort', 'rescale_images', 'toc_title', ['prefer_author_sort', 'rescale_images', 'toc_title',
'dont_compress',] 'dont_compress', 'no_inline_toc']
) )
self.db, self.book_id = db, book_id self.db, self.book_id = db, book_id
self.initialize_options(get_option, get_help, db, book_id) self.initialize_options(get_option, get_help, db, book_id)

View File

@ -144,7 +144,7 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="2"> <item row="6" column="0" colspan="2">
<widget class="QCheckBox" name="opt_remember_window_size"> <widget class="QCheckBox" name="opt_remember_window_size">
<property name="text"> <property name="text">
<string>Remember last used &amp;window size</string> <string>Remember last used &amp;window size</string>
@ -174,9 +174,33 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="hyphenate">
<property name="text">
<string>H&amp;yphenate (break line in the middle of large words)</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="hyphenate_default_lang">
<property name="toolTip">
<string>The default language to use for hyphenation rules. If the book does not specify a language, this will be used.</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Default &amp;language for hyphenation:</string>
</property>
<property name="buddy">
<cstring>hyphenate_default_lang</cstring>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<widget class="QGroupBox" name="groupBox_2"> <widget class="QGroupBox" name="groupBox_2">
<property name="title"> <property name="title">
<string>&amp;User stylesheet</string> <string>&amp;User stylesheet</string>
@ -226,8 +250,8 @@
<slot>accept()</slot> <slot>accept()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>248</x> <x>252</x>
<y>254</y> <y>569</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>157</x> <x>157</x>
@ -242,8 +266,8 @@
<slot>reject()</slot> <slot>reject()</slot>
<hints> <hints>
<hint type="sourcelabel"> <hint type="sourcelabel">
<x>316</x> <x>320</x>
<y>260</y> <y>569</y>
</hint> </hint>
<hint type="destinationlabel"> <hint type="destinationlabel">
<x>286</x> <x>286</x>
@ -251,5 +275,21 @@
</hint> </hint>
</hints> </hints>
</connection> </connection>
<connection>
<sender>hyphenate</sender>
<signal>toggled(bool)</signal>
<receiver>hyphenate_default_lang</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>83</x>
<y>279</y>
</hint>
<hint type="destinationlabel">
<x>349</x>
<y>312</y>
</hint>
</hints>
</connection>
</connections> </connections>
</ui> </ui>

View File

@ -14,7 +14,7 @@ from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
from calibre.utils.config import Config, StringConfig from calibre.utils.config import Config, StringConfig
from calibre.gui2.viewer.config_ui import Ui_Dialog from calibre.gui2.viewer.config_ui import Ui_Dialog
from calibre.gui2.viewer.js import bookmarks, referencing from calibre.gui2.viewer.js import bookmarks, referencing, hyphenation
from calibre.ptempfile import PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryFile
from calibre.constants import iswindows from calibre.constants import iswindows
from calibre import prints from calibre import prints
@ -61,6 +61,9 @@ def config(defaults=None):
help=_('Set the user CSS stylesheet. This can be used to customize the look of all books.')) help=_('Set the user CSS stylesheet. This can be used to customize the look of all books.'))
c.add_opt('max_view_width', default=6000, c.add_opt('max_view_width', default=6000,
help=_('Maximum width of the viewer window, in pixels.')) help=_('Maximum width of the viewer window, in pixels.'))
c.add_opt('hyphenate', default=False, help=_('Hyphenate text'))
c.add_opt('hyphenate_default_lang', default='en',
help=_('Default language for hyphenation rules'))
fonts = c.add_group('FONTS', _('Font options')) fonts = c.add_group('FONTS', _('Font options'))
fonts('serif_family', default='Times New Roman' if iswindows else 'Liberation Serif', fonts('serif_family', default='Times New Roman' if iswindows else 'Liberation Serif',
@ -106,6 +109,15 @@ class ConfigDialog(QDialog, Ui_Dialog):
self.css.setPlainText(opts.user_css) self.css.setPlainText(opts.user_css)
self.css.setToolTip(_('Set the user CSS stylesheet. This can be used to customize the look of all books.')) self.css.setToolTip(_('Set the user CSS stylesheet. This can be used to customize the look of all books.'))
self.max_view_width.setValue(opts.max_view_width) self.max_view_width.setValue(opts.max_view_width)
from calibre.resources import hyphenate
for x in sorted(hyphenate['languages'].split(',')):
self.hyphenate_default_lang.addItem(x)
idx = self.hyphenate_default_lang.findText(opts.hyphenate_default_lang)
if idx == -1:
idx = self.hyphenate_default_lang.findText('en')
self.hyphenate_default_lang.setCurrentIndex(idx)
self.hyphenate.setChecked(opts.hyphenate)
self.hyphenate_default_lang.setEnabled(opts.hyphenate)
def accept(self, *args): def accept(self, *args):
@ -119,6 +131,9 @@ class ConfigDialog(QDialog, Ui_Dialog):
c.set('user_css', unicode(self.css.toPlainText())) c.set('user_css', unicode(self.css.toPlainText()))
c.set('remember_window_size', self.opt_remember_window_size.isChecked()) c.set('remember_window_size', self.opt_remember_window_size.isChecked())
c.set('max_view_width', int(self.max_view_width.value())) c.set('max_view_width', int(self.max_view_width.value()))
c.set('hyphenate', self.hyphenate.isChecked())
c.set('hyphenate_default_lang',
self.hyphenate_default_lang.currentText())
return QDialog.accept(self, *args) return QDialog.accept(self, *args)
@ -141,12 +156,14 @@ class Document(QWebPage):
if d.exec_() == QDialog.Accepted: if d.exec_() == QDialog.Accepted:
self.set_font_settings() self.set_font_settings()
self.set_user_stylesheet() self.set_user_stylesheet()
self.misc_config()
self.triggerAction(QWebPage.Reload) self.triggerAction(QWebPage.Reload)
def __init__(self, *args): def __init__(self, *args):
QWebPage.__init__(self, *args) QWebPage.__init__(self, *args)
self.setObjectName("py_bridge") self.setObjectName("py_bridge")
self.debug_javascript = False self.debug_javascript = False
self.current_language = None
#self.js_bridge = PythonJS(self.js_callback) #self.js_bridge = PythonJS(self.js_callback)
self.setLinkDelegationPolicy(self.DelegateAllLinks) self.setLinkDelegationPolicy(self.DelegateAllLinks)
@ -170,6 +187,7 @@ class Document(QWebPage):
# Miscellaneous # Miscellaneous
settings.setAttribute(QWebSettings.LinksIncludedInFocusChain, True) settings.setAttribute(QWebSettings.LinksIncludedInFocusChain, True)
self.set_user_stylesheet() self.set_user_stylesheet()
self.misc_config()
# Load jQuery # Load jQuery
self.connect(self.mainFrame(), SIGNAL('javaScriptWindowObjectCleared()'), self.connect(self.mainFrame(), SIGNAL('javaScriptWindowObjectCleared()'),
@ -182,18 +200,39 @@ class Document(QWebPage):
pt.close() pt.close()
self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(pt.name)) self.settings().setUserStyleSheetUrl(QUrl.fromLocalFile(pt.name))
def misc_config(self):
opts = config().parse()
self.hyphenate = opts.hyphenate
self.hyphenate_default_lang = opts.hyphenate_default_lang
def load_javascript_libraries(self): def load_javascript_libraries(self):
self.mainFrame().addToJavaScriptWindowObject("py_bridge", self) self.mainFrame().addToJavaScriptWindowObject("py_bridge", self)
from calibre.resources import jquery, jquery_scrollTo from calibre.resources import jquery, jquery_scrollTo, hyphenate
self.javascript(jquery) self.javascript(jquery)
self.javascript(jquery_scrollTo) self.javascript(jquery_scrollTo)
self.javascript(bookmarks) self.javascript(bookmarks)
self.javascript(referencing) self.javascript(referencing)
self.javascript(hyphenation)
default_lang = self.hyphenate_default_lang
lang = self.current_language
if not lang:
lang = default_lang
lang = lang.lower()[:2]
if lang not in hyphenate['languages']:
lang = default_lang
self.loaded_lang = lang
self.javascript(hyphenate['Hyphenator.js'].decode('utf-8'))
self.javascript(hyphenate[lang+'.js'].decode('utf-8'))
@pyqtSignature("") @pyqtSignature("")
def animated_scroll_done(self): def animated_scroll_done(self):
self.emit(SIGNAL('animated_scroll_done()')) self.emit(SIGNAL('animated_scroll_done()'))
@pyqtSignature("")
def init_hyphenate(self):
if self.hyphenate:
self.javascript('do_hyphenation("%s")'%self.loaded_lang)
@pyqtSignature("QString") @pyqtSignature("QString")
def debug(self, msg): def debug(self, msg):
prints(msg) prints(msg)
@ -401,6 +440,12 @@ class DocumentView(QWebView):
def content_size(self): def content_size(self):
return self.document.width, self.document.height return self.document.width, self.document.height
@dynamic_property
def current_language(self):
def fget(self): return self.document.current_language
def fset(self, val): self.document.current_language = val
return property(fget=fget, fset=fset)
def search(self, text): def search(self, text):
return self.findText(text) return self.findText(text)

View File

@ -132,3 +132,25 @@ $(document.body).click(function(e) {
$(document).ready(enter_reference_mode); $(document).ready(enter_reference_mode);
''' '''
hyphenation = '''
function init_hyphenate() {
window.py_bridge.init_hyphenate();
}
document.addEventListener("DOMContentLoaded", init_hyphenate, false);
function do_hyphenation(lang) {
Hyphenator.config(
{
'minwordlength' : 6,
//'hyphenchar' : '|',
'displaytogglebox' : false,
'remoteloading' : false,
'onerrorhandler' : function (e) {
window.py_bridge.debug(e);
}
});
Hyphenator.hyphenate(document.body, lang);
}
'''

View File

@ -563,6 +563,7 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
self.close_progress_indicator() self.close_progress_indicator()
else: else:
self.metadata.show_opf(self.iterator.opf, os.path.splitext(pathtoebook)[1][1:]) self.metadata.show_opf(self.iterator.opf, os.path.splitext(pathtoebook)[1][1:])
self.view.current_language = self.iterator.language
title = self.iterator.opf.title title = self.iterator.opf.title
if not title: if not title:
title = os.path.splitext(os.path.basename(pathtoebook))[0] title = os.path.splitext(os.path.basename(pathtoebook))[0]

View File

@ -186,12 +186,17 @@ class resources(OptionlessCommand):
def get_hyphenate(self): def get_hyphenate(self):
sdir = os.path.join('src', 'calibre', 'gui2', 'viewer', 'hyphenate') sdir = os.path.join('src', 'calibre', 'gui2', 'viewer', 'hyphenate')
resources, max = {}, 0 resources, max = {}, 0
languages = set([])
for f in glob.glob(os.path.join(sdir, 'patterns', '*.js')) + \ for f in glob.glob(os.path.join(sdir, 'patterns', '*.js')) + \
[os.path.join(sdir, 'Hyphenator.js')]: [os.path.join(sdir, 'Hyphenator.js')]:
f = os.path.abspath(f) f = os.path.abspath(f)
resources[os.path.basename(f)] = self.get(f) b = os.path.basename(f)
resources[b] = self.get(f)
if b != 'Hyphenator.js':
languages.add(b.split('.')[0])
mtime = os.stat(f).st_mtime mtime = os.stat(f).st_mtime
max = mtime if mtime > max else max max = mtime if mtime > max else max
resources['languages'] = ','.join(languages)
return resources, max return resources, max
def run(self): def run(self):
@ -205,7 +210,7 @@ class resources(OptionlessCommand):
static, smax = self.get_static_resources() static, smax = self.get_static_resources()
recipes, rmax = self.get_recipes() recipes, rmax = self.get_recipes()
hyphenate, hmax = self.get_hyphenate() hyphenate, hmax = self.get_hyphenate()
amax = max(rmax, smax, hmax) amax = max(rmax, smax, hmax, os.stat(__file__).st_mtime)
if newer([dest], RESOURCES.values()) or os.stat(dest).st_mtime < amax: if newer([dest], RESOURCES.values()) or os.stat(dest).st_mtime < amax:
print 'Compiling resources...' print 'Compiling resources...'
with open(dest, 'wb') as f: with open(dest, 'wb') as f: