mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
6ba9ee4bd1
@ -2,7 +2,7 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
__appname__ = 'calibre'
|
||||
__version__ = '0.6.1'
|
||||
__version__ = '0.6.2'
|
||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||
|
||||
import re
|
||||
|
@ -199,6 +199,17 @@ class SonyReaderOutput(OutputProfile):
|
||||
fbase = 12
|
||||
fsizes = [7.5, 9, 10, 12, 15.5, 20, 22, 24]
|
||||
|
||||
class JetBook5Output(OutputProfile):
|
||||
|
||||
name = 'JetBook 5-inch'
|
||||
short_name = 'jetbook5'
|
||||
description = _('This profile is intended for the 5-inch JetBook.')
|
||||
|
||||
screen_size = (480, 640)
|
||||
dpi = 168.451
|
||||
|
||||
|
||||
|
||||
class SonyReaderLandscapeOutput(SonyReaderOutput):
|
||||
|
||||
name = 'Sony Reader Landscape'
|
||||
@ -334,4 +345,4 @@ class IRexDR1000Output(OutputProfile):
|
||||
output_profiles = [OutputProfile, SonyReaderOutput, MSReaderOutput,
|
||||
MobipocketOutput, HanlinV3Output, CybookG3Output, CybookOpusOutput,
|
||||
KindleOutput, SonyReaderLandscapeOutput, KindleDXOutput, IlliadOutput,
|
||||
IRexDR1000Output]
|
||||
IRexDR1000Output, JetBook5Output]
|
||||
|
@ -108,11 +108,16 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
<title>%(title)s</title>
|
||||
<style type="text/css">
|
||||
body {
|
||||
background: white no-repeat fixed center center;
|
||||
text-align: center;
|
||||
vertical-align: center;
|
||||
overflow: hidden;
|
||||
font-size: 18px;
|
||||
font-size: 16pt;
|
||||
}
|
||||
.logo {
|
||||
width: 510px; height: 390px;
|
||||
text-align:center;
|
||||
font-size: 1pt;
|
||||
overflow:hidden;
|
||||
}
|
||||
h1 { font-family: serif; }
|
||||
h2, h4 { font-family: monospace; }
|
||||
@ -120,19 +125,11 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
</head>
|
||||
<body>
|
||||
<h1>%(title)s</h1>
|
||||
<br/><br/>
|
||||
<div style="position:relative">
|
||||
<div style="position: absolute; left: 0; top: 0; width:100%%; height:100%%; vertical-align:center">
|
||||
<img src="%(img)s" alt="calibre" style="opacity:0.3"/>
|
||||
</div>
|
||||
<div style="position: absolute; left: 0; top: 0; width:100%%; height:100%%; vertical-align:center">
|
||||
<h2>%(date)s</h2>
|
||||
<br/><br/><br/><br/><br/>
|
||||
<h3>%(author)s</h3>
|
||||
<br/><br/><br/><br/><br/><br/><br/><br/><br/>
|
||||
<h4>Produced by %(app)s</h4>
|
||||
</div>
|
||||
<div style="text-align:center">
|
||||
<img class="logo" src="%(img)s" alt="calibre logo" />
|
||||
</div>
|
||||
<h2>%(author)s</h2>
|
||||
<h4>Produced by %(app)s</h4>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
@ -201,7 +198,7 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
images_rc
|
||||
m = self.oeb.metadata
|
||||
title = unicode(m.title[0])
|
||||
a = [unicode(x) for x in m.creators if m.role == 'aut']
|
||||
a = [unicode(x) for x in m.creator if x.role == 'aut']
|
||||
author = authors_to_string(a)
|
||||
if QApplication.instance() is None: QApplication([])
|
||||
f = QFile(':/library')
|
||||
@ -211,8 +208,9 @@ class EPUBOutput(OutputFormatPlugin):
|
||||
'calibre-logo.png')
|
||||
self.oeb.manifest.add(id, href, 'image/png', data=img_data)
|
||||
title, author = map(prepare_string_for_xml, (title, author))
|
||||
if not author or not author.strip():
|
||||
author = strftime('%d %b, %Y')
|
||||
html = self.TITLEPAGE%dict(title=title, author=author,
|
||||
date=strftime('%d %b, %Y'),
|
||||
app=__appname__ +' '+__version__,
|
||||
img=href)
|
||||
id, href = self.oeb.manifest.generate('calibre-titlepage',
|
||||
|
@ -6,6 +6,16 @@ __docformat__ = 'restructuredtext en'
|
||||
'''
|
||||
ebook-meta
|
||||
'''
|
||||
import sys, os
|
||||
|
||||
from calibre.utils.config import StringConfig
|
||||
from calibre.customize.ui import metadata_readers, metadata_writers
|
||||
from calibre.ebooks.metadata.meta import get_metadata, set_metadata
|
||||
from calibre.ebooks.metadata import string_to_authors, authors_to_sort_string, \
|
||||
title_sort, MetaInformation
|
||||
from calibre.ebooks.lrf.meta import LRFMetaFile
|
||||
from calibre import prints
|
||||
|
||||
USAGE='%%prog ebook_file [' + _('options') + ']\n' + \
|
||||
_('''
|
||||
Read/Write metadata from/to ebook files.
|
||||
@ -19,15 +29,7 @@ some metadata on a file type that does not support it, the metadata will be
|
||||
silently ignored.
|
||||
''')
|
||||
|
||||
import sys, os
|
||||
|
||||
from calibre.utils.config import StringConfig
|
||||
from calibre.customize.ui import metadata_readers, metadata_writers
|
||||
from calibre.ebooks.metadata.meta import get_metadata, set_metadata
|
||||
from calibre.ebooks.metadata import string_to_authors, authors_to_sort_string, \
|
||||
title_sort, MetaInformation
|
||||
from calibre.ebooks.lrf.meta import LRFMetaFile
|
||||
from calibre import prints
|
||||
|
||||
def config():
|
||||
c = StringConfig('')
|
||||
|
@ -303,7 +303,12 @@ class MobiReader(object):
|
||||
self.cleanup_html()
|
||||
|
||||
self.log.debug('Parsing HTML...')
|
||||
root = html.fromstring(self.processed_html)
|
||||
try:
|
||||
root = html.fromstring(self.processed_html)
|
||||
except:
|
||||
self.log.warning('MOBI markup appears to contain random bytes. Stripping.')
|
||||
self.processed_html = self.remove_random_bytes(self.processed_html)
|
||||
root = html.fromstring(self.processed_html)
|
||||
if root.xpath('descendant::p/descendant::p'):
|
||||
from lxml.html import soupparser
|
||||
self.log.warning('Malformed markup, parsing using BeautifulSoup')
|
||||
@ -444,7 +449,10 @@ class MobiReader(object):
|
||||
self.processed_html = '<html><p>' + self.processed_html.replace('\n\n', '<p>') + '</html>'
|
||||
self.processed_html = self.processed_html.replace('\r\n', '\n')
|
||||
self.processed_html = self.processed_html.replace('> <', '>\n<')
|
||||
self.processed_html = re.sub('\x14|\x15|\x1c|\x1d|\xef|\x12|\x13|\xec', '', self.processed_html)
|
||||
|
||||
def remove_random_bytes(self, html):
|
||||
return re.sub('\x14|\x15|\x1c|\x1d|\xef|\x12|\x13|\xec',
|
||||
'', html)
|
||||
|
||||
def ensure_unit(self, raw, unit='px'):
|
||||
if re.search(r'\d+$', raw) is not None:
|
||||
|
@ -64,4 +64,15 @@ class ODTInput(InputFormatPlugin):
|
||||
accelerators):
|
||||
return Extract()(stream, '.')
|
||||
|
||||
def postprocess_book(self, oeb, opts, log):
|
||||
# Fix <p><div> constructs as the asinine epubchecker complains
|
||||
# about them
|
||||
from calibre.ebooks.oeb.base import XPath, XHTML
|
||||
path = XPath('//h:p/h:div')
|
||||
for item in oeb.spine:
|
||||
root = item.data
|
||||
if not hasattr(root, 'xpath'): continue
|
||||
for div in path(root):
|
||||
div.getparent().tag = XHTML('div')
|
||||
|
||||
|
||||
|
@ -694,7 +694,6 @@ class Metadata(object):
|
||||
def to_opf2(self, parent=None):
|
||||
nsmap = self._opf2_nsmap
|
||||
nsrmap = dict((value, key) for key, value in nsmap.items())
|
||||
nsmap.pop('opf', '')
|
||||
elem = element(parent, OPF('metadata'), nsmap=nsmap)
|
||||
for term in self.items:
|
||||
for item in self.items[term]:
|
||||
@ -815,15 +814,28 @@ class Manifest(object):
|
||||
data = etree.fromstring(data, parser=RECOVER_PARSER)
|
||||
return data
|
||||
data = first_pass(data)
|
||||
# Force into the XHTML namespace
|
||||
|
||||
# Handle weird (non-HTML/fragment) files
|
||||
if barename(data.tag) != 'html':
|
||||
self.oeb.log.warn('File %r does not appear to be (X)HTML'%self.href)
|
||||
nroot = etree.fromstring('<html></html>')
|
||||
has_body = False
|
||||
for child in list(data):
|
||||
if barename(child.tag) == 'body':
|
||||
has_body = True
|
||||
break
|
||||
parent = nroot
|
||||
if not has_body:
|
||||
self.oeb.log.warn('File %r appears to be a HTML fragment'%self.href)
|
||||
nroot = etree.fromstring('<html><body/></html>')
|
||||
parent = nroot[0]
|
||||
for child in list(data):
|
||||
child.getparent().remove(child)
|
||||
nroot.append(child)
|
||||
parent.append(child)
|
||||
data = nroot
|
||||
elif not namespace(data.tag):
|
||||
|
||||
# Force into the XHTML namespace
|
||||
if not namespace(data.tag):
|
||||
data.attrib['xmlns'] = XHTML_NS
|
||||
data = etree.tostring(data, encoding=unicode)
|
||||
try:
|
||||
|
@ -3,7 +3,7 @@ __license__ = 'GPL 3'
|
||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import os
|
||||
import os, re
|
||||
|
||||
from lxml import etree
|
||||
|
||||
@ -34,6 +34,10 @@ class OEBOutput(OutputFormatPlugin):
|
||||
if root is not None:
|
||||
raw = etree.tostring(root, pretty_print=True,
|
||||
encoding='utf-8', xml_declaration=True)
|
||||
if key == OPF_MIME:
|
||||
# Needed as I can't get lxml to output opf:role and
|
||||
# not output <opf:metadata> as well
|
||||
raw = re.sub(r'(<[/]{0,1})opf:', r'\1', raw)
|
||||
with open(href, 'wb') as f:
|
||||
f.write(raw)
|
||||
|
||||
|
@ -19,7 +19,7 @@ def meta_info_to_oeb_metadata(mi, m, log):
|
||||
m.add('title', mi.title_sort)
|
||||
m.title[0].file_as = mi.title_sort
|
||||
if mi.authors:
|
||||
m.filter('creator', lambda x : x.role.lower() == 'aut')
|
||||
m.filter('creator', lambda x : x.role.lower() in ['aut', ''])
|
||||
for a in mi.authors:
|
||||
attrib = {'role':'aut'}
|
||||
if mi.author_sort:
|
||||
|
@ -1128,6 +1128,7 @@ class SearchBox(QLineEdit):
|
||||
self.home(False)
|
||||
self.initial_state = True
|
||||
self.setStyleSheet("background-color: white")
|
||||
self.emit(SIGNAL('cleared()'))
|
||||
|
||||
def clear(self):
|
||||
self.clear_to_help()
|
||||
|
@ -456,6 +456,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
||||
SIGNAL('count_changed(int)'), self.location_view.count_changed)
|
||||
self.connect(self.library_view.model(), SIGNAL('count_changed(int)'),
|
||||
self.tags_view.recount)
|
||||
self.connect(self.search, SIGNAL('cleared()'), self.tags_view.clear)
|
||||
self.library_view.model().count_changed()
|
||||
########################### Cover Flow ################################
|
||||
self.cover_flow = None
|
||||
@ -1409,7 +1410,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
||||
self.view_format(row, format)
|
||||
break
|
||||
if not in_prefs:
|
||||
self.view_format(row, format[0])
|
||||
self.view_format(row, formats[0])
|
||||
else:
|
||||
paths = self.current_view().model().paths(rows)
|
||||
for path in paths:
|
||||
|
@ -36,6 +36,9 @@ class TagsView(QTreeView):
|
||||
self.emit(SIGNAL('tags_marked(PyQt_PyObject, PyQt_PyObject)'),
|
||||
self._model.tokens(), self.match_all.isChecked())
|
||||
|
||||
def clear(self):
|
||||
self.model().clear_state()
|
||||
|
||||
def recount(self, *args):
|
||||
ci = self.currentIndex()
|
||||
if not ci.isValid():
|
||||
@ -119,6 +122,11 @@ class TagsModel(QStandardItemModel):
|
||||
self._data[category], self.cmap[r], self.bold_font, self.icon_map))
|
||||
#self.reset()
|
||||
|
||||
def clear_state(self):
|
||||
for category in self._data.values():
|
||||
for tag in category:
|
||||
tag.state = 0
|
||||
self.refresh()
|
||||
|
||||
def reinit(self, *args, **kwargs):
|
||||
if not self.ignore_next_search:
|
||||
|
@ -166,6 +166,11 @@ def fetch_scheduled_recipe(recipe, script):
|
||||
recs.append(('base_font_size', lf['base_font_size'],
|
||||
OptionRecommendation.HIGH))
|
||||
|
||||
lr = load_defaults('lrf_output')
|
||||
if lr.get('header', False):
|
||||
recs.append(('header', True, OptionRecommendation.HIGH))
|
||||
recs.append(('header_format', '%t', OptionRecommendation.HIGH))
|
||||
|
||||
args = [script, pt.name, recs]
|
||||
if recipe.needs_subscription:
|
||||
x = config.get('recipe_account_info_%s'%recipe.id, False)
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user