mirror of
git://github.com/kovidgoyal/calibre.git
synced 2026-01-25 22:34:56 +01:00
Merge from trunk
This commit is contained in:
commit
cf8e89aed5
7 changed files with 84 additions and 13 deletions
|
|
@ -85,7 +85,11 @@ def add_result(self, result):
|
|||
isbns, min_year = xisbn.get_isbn_pool(isbn)
|
||||
if not isbns:
|
||||
isbns = frozenset([isbn])
|
||||
self.pools[isbns] = pool = (min_year, [])
|
||||
if isbns in self.pools:
|
||||
# xISBN had a brain fart
|
||||
pool = self.pools[isbns]
|
||||
else:
|
||||
self.pools[isbns] = pool = (min_year, [])
|
||||
|
||||
if not self.pool_has_result_from_same_source(pool, result):
|
||||
pool[1].append(result)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,11 @@ def fetch_data(self, isbn):
|
|||
ans.append(rec)
|
||||
return ans
|
||||
|
||||
def isbns_in_data(self, data):
|
||||
for rec in data:
|
||||
for i in rec.get('isbn', []):
|
||||
yield i
|
||||
|
||||
def get_data(self, isbn):
|
||||
isbn = self.purify(isbn)
|
||||
with self.lock:
|
||||
|
|
@ -57,9 +62,8 @@ def get_data(self, isbn):
|
|||
data = []
|
||||
id_ = len(self._data)
|
||||
self._data.append(data)
|
||||
for rec in data:
|
||||
for i in rec.get('isbn', []):
|
||||
self._map[i] = id_
|
||||
for i in self.isbns_in_data(data):
|
||||
self._map[i] = id_
|
||||
self._map[isbn] = id_
|
||||
return self._data[self._map[isbn]]
|
||||
|
||||
|
|
|
|||
|
|
@ -443,11 +443,15 @@ def mobimlize_elem(self, elem, stylizer, bstate, istates,
|
|||
tag = 'span' if tag == 'td' else 'div'
|
||||
|
||||
if tag == 'table':
|
||||
col = style.backgroundColor
|
||||
if col:
|
||||
elem.set('bgcolor', col)
|
||||
css = style.cssdict()
|
||||
if 'border' in css or 'border-width' in css:
|
||||
elem.set('border', '1')
|
||||
if tag in TABLE_TAGS:
|
||||
for attr in ('rowspan', 'colspan', 'width', 'border', 'scope'):
|
||||
for attr in ('rowspan', 'colspan', 'width', 'border', 'scope',
|
||||
'bgcolor'):
|
||||
if attr in elem.attrib:
|
||||
istate.attrib[attr] = elem.attrib[attr]
|
||||
if tag == 'q':
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
import os, itertools, re, logging, copy, unicodedata
|
||||
from weakref import WeakKeyDictionary
|
||||
from xml.dom import SyntaxErr as CSSSyntaxError
|
||||
import cssutils
|
||||
from cssutils.css import (CSSStyleRule, CSSPageRule, CSSStyleDeclaration,
|
||||
CSSFontFaceRule, cssproperties)
|
||||
try:
|
||||
|
|
@ -20,7 +19,8 @@
|
|||
except ImportError:
|
||||
# cssutils >= 0.9.8
|
||||
from cssutils.css import PropertyValue as CSSValueList
|
||||
from cssutils import profile as cssprofiles
|
||||
from cssutils import (profile as cssprofiles, parseString, parseStyle, log as
|
||||
cssutils_log, CSSParser, profiles)
|
||||
from lxml import etree
|
||||
from lxml.cssselect import css_to_xpath, ExpressionError, SelectorSyntaxError
|
||||
from calibre import force_unicode
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
from calibre.ebooks.oeb.base import XHTML, XHTML_NS, CSS_MIME, OEB_STYLES
|
||||
from calibre.ebooks.oeb.base import XPNSMAP, xpath, urlnormalize
|
||||
|
||||
cssutils.log.setLevel(logging.WARN)
|
||||
cssutils_log.setLevel(logging.WARN)
|
||||
|
||||
_html_css_stylesheet = None
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ def html_css_stylesheet():
|
|||
global _html_css_stylesheet
|
||||
if _html_css_stylesheet is None:
|
||||
html_css = open(P('templates/html.css'), 'rb').read()
|
||||
_html_css_stylesheet = cssutils.parseString(html_css)
|
||||
_html_css_stylesheet = parseString(html_css)
|
||||
_html_css_stylesheet.namespaces['h'] = XHTML_NS
|
||||
return _html_css_stylesheet
|
||||
|
||||
|
|
@ -157,11 +157,11 @@ def __init__(self, tree, path, oeb, opts, profile=None,
|
|||
|
||||
# Add cssutils parsing profiles from output_profile
|
||||
for profile in self.opts.output_profile.extra_css_modules:
|
||||
cssutils.profile.addProfile(profile['name'],
|
||||
cssprofiles.addProfile(profile['name'],
|
||||
profile['props'],
|
||||
profile['macros'])
|
||||
|
||||
parser = cssutils.CSSParser(fetcher=self._fetch_css_file,
|
||||
parser = CSSParser(fetcher=self._fetch_css_file,
|
||||
log=logging.getLogger('calibre.css'))
|
||||
self.font_face_rules = []
|
||||
for elem in head:
|
||||
|
|
@ -473,6 +473,7 @@ def __init__(self, element, stylizer):
|
|||
self._width = None
|
||||
self._height = None
|
||||
self._lineHeight = None
|
||||
self._bgcolor = None
|
||||
stylizer._styles[element] = self
|
||||
|
||||
def set(self, prop, val):
|
||||
|
|
@ -533,6 +534,48 @@ def _unit_convert(self, value, base=None, font=None):
|
|||
def pt_to_px(self, value):
|
||||
return (self._profile.dpi / 72.0) * value
|
||||
|
||||
@property
|
||||
def backgroundColor(self):
|
||||
'''
|
||||
Return the background color by parsing both the background-color and
|
||||
background shortcut properties. Note that inheritance/default values
|
||||
are not used. None is returned if no background color is set.
|
||||
'''
|
||||
|
||||
def validate_color(col):
|
||||
return cssprofiles.validateWithProfile('color',
|
||||
col,
|
||||
profiles=[profiles.Profiles.CSS_LEVEL_2])[1]
|
||||
|
||||
if self._bgcolor is None:
|
||||
col = None
|
||||
val = self._style.get('background-color', None)
|
||||
if val and validate_color(val):
|
||||
col = val
|
||||
else:
|
||||
val = self._style.get('background', None)
|
||||
if val is not None:
|
||||
try:
|
||||
style = parseStyle('background: '+val)
|
||||
val = style.getProperty('background').cssValue
|
||||
try:
|
||||
val = list(val)
|
||||
except:
|
||||
# val is CSSPrimitiveValue
|
||||
val = [val]
|
||||
for c in val:
|
||||
c = c.cssText
|
||||
if validate_color(c):
|
||||
col = c
|
||||
break
|
||||
except:
|
||||
pass
|
||||
if col is None:
|
||||
self._bgcolor = False
|
||||
else:
|
||||
self._bgcolor = col
|
||||
return self._bgcolor if self._bgcolor else None
|
||||
|
||||
@property
|
||||
def fontSize(self):
|
||||
def normalize_fontsize(value, base):
|
||||
|
|
|
|||
|
|
@ -287,6 +287,18 @@ def mark_dirty(self):
|
|||
'rate of approximately 1 book every three seconds.'), show=True)
|
||||
|
||||
def restore_database(self):
|
||||
m = self.gui.library_view.model()
|
||||
db = m.db
|
||||
if (iswindows and len(db.library_path) >
|
||||
LibraryDatabase2.WINDOWS_LIBRARY_PATH_LIMIT):
|
||||
return error_dialog(self.gui, _('Too long'),
|
||||
_('Path to library too long. Must be less than'
|
||||
' %d characters. Move your library to a location with'
|
||||
' a shorter path using Windows Explorer, then point'
|
||||
' calibre to the new location and try again.')%
|
||||
LibraryDatabase2.WINDOWS_LIBRARY_PATH_LIMIT,
|
||||
show=True)
|
||||
|
||||
from calibre.gui2.dialogs.restore_library import restore_database
|
||||
m = self.gui.library_view.model()
|
||||
m.stop_metadata_backup()
|
||||
|
|
|
|||
|
|
@ -388,6 +388,10 @@ def download_cover(self, *args):
|
|||
|
||||
def apply_changes(self):
|
||||
self.changed.add(self.book_id)
|
||||
if self.db is None:
|
||||
# break_cycles has already been called, don't know why this should
|
||||
# happen but a user reported it
|
||||
return True
|
||||
for widget in self.basic_metadata_widgets:
|
||||
try:
|
||||
if not widget.commit(self.db, self.book_id):
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@
|
|||
E = ElementMaker(namespace=NS, nsmap={None:NS})
|
||||
|
||||
def iterate_over_builtin_recipe_files():
|
||||
exclude = ['craigslist', 'iht', 'outlook_india', 'toronto_sun',
|
||||
'indian_express', 'india_today', 'livemint']
|
||||
exclude = ['craigslist', 'iht', 'toronto_sun',
|
||||
'india_today', 'livemint']
|
||||
d = os.path.dirname
|
||||
base = os.path.join(d(d(d(d(d(d(os.path.abspath(__file__))))))), 'recipes')
|
||||
for f in os.listdir(base):
|
||||
|
|
|
|||
Loading…
Reference in a new issue