Merge from trunk

This commit is contained in:
kiwidude 2011-06-17 17:22:17 +01:00
commit cf8e89aed5
7 changed files with 84 additions and 13 deletions

View File

@ -85,6 +85,10 @@ class ISBNMerge(object):
isbns, min_year = xisbn.get_isbn_pool(isbn) isbns, min_year = xisbn.get_isbn_pool(isbn)
if not isbns: if not isbns:
isbns = frozenset([isbn]) isbns = frozenset([isbn])
if isbns in self.pools:
# xISBN had a brain fart
pool = self.pools[isbns]
else:
self.pools[isbns] = pool = (min_year, []) self.pools[isbns] = pool = (min_year, [])
if not self.pool_has_result_from_same_source(pool, result): if not self.pool_has_result_from_same_source(pool, result):

View File

@ -45,6 +45,11 @@ class xISBN(object):
ans.append(rec) ans.append(rec)
return ans 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): def get_data(self, isbn):
isbn = self.purify(isbn) isbn = self.purify(isbn)
with self.lock: with self.lock:
@ -57,8 +62,7 @@ class xISBN(object):
data = [] data = []
id_ = len(self._data) id_ = len(self._data)
self._data.append(data) self._data.append(data)
for rec in data: for i in self.isbns_in_data(data):
for i in rec.get('isbn', []):
self._map[i] = id_ self._map[i] = id_
self._map[isbn] = id_ self._map[isbn] = id_
return self._data[self._map[isbn]] return self._data[self._map[isbn]]

View File

@ -443,11 +443,15 @@ class MobiMLizer(object):
tag = 'span' if tag == 'td' else 'div' tag = 'span' if tag == 'td' else 'div'
if tag == 'table': if tag == 'table':
col = style.backgroundColor
if col:
elem.set('bgcolor', col)
css = style.cssdict() css = style.cssdict()
if 'border' in css or 'border-width' in css: if 'border' in css or 'border-width' in css:
elem.set('border', '1') elem.set('border', '1')
if tag in TABLE_TAGS: 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: if attr in elem.attrib:
istate.attrib[attr] = elem.attrib[attr] istate.attrib[attr] = elem.attrib[attr]
if tag == 'q': if tag == 'q':

View File

@ -11,7 +11,6 @@ __copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
import os, itertools, re, logging, copy, unicodedata import os, itertools, re, logging, copy, unicodedata
from weakref import WeakKeyDictionary from weakref import WeakKeyDictionary
from xml.dom import SyntaxErr as CSSSyntaxError from xml.dom import SyntaxErr as CSSSyntaxError
import cssutils
from cssutils.css import (CSSStyleRule, CSSPageRule, CSSStyleDeclaration, from cssutils.css import (CSSStyleRule, CSSPageRule, CSSStyleDeclaration,
CSSFontFaceRule, cssproperties) CSSFontFaceRule, cssproperties)
try: try:
@ -20,7 +19,8 @@ try:
except ImportError: except ImportError:
# cssutils >= 0.9.8 # cssutils >= 0.9.8
from cssutils.css import PropertyValue as CSSValueList 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 import etree
from lxml.cssselect import css_to_xpath, ExpressionError, SelectorSyntaxError from lxml.cssselect import css_to_xpath, ExpressionError, SelectorSyntaxError
from calibre import force_unicode from calibre import force_unicode
@ -28,7 +28,7 @@ from calibre.ebooks import unit_convert
from calibre.ebooks.oeb.base import XHTML, XHTML_NS, CSS_MIME, OEB_STYLES from calibre.ebooks.oeb.base import XHTML, XHTML_NS, CSS_MIME, OEB_STYLES
from calibre.ebooks.oeb.base import XPNSMAP, xpath, urlnormalize from calibre.ebooks.oeb.base import XPNSMAP, xpath, urlnormalize
cssutils.log.setLevel(logging.WARN) cssutils_log.setLevel(logging.WARN)
_html_css_stylesheet = None _html_css_stylesheet = None
@ -36,7 +36,7 @@ def html_css_stylesheet():
global _html_css_stylesheet global _html_css_stylesheet
if _html_css_stylesheet is None: if _html_css_stylesheet is None:
html_css = open(P('templates/html.css'), 'rb').read() 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 _html_css_stylesheet.namespaces['h'] = XHTML_NS
return _html_css_stylesheet return _html_css_stylesheet
@ -157,11 +157,11 @@ class Stylizer(object):
# Add cssutils parsing profiles from output_profile # Add cssutils parsing profiles from output_profile
for profile in self.opts.output_profile.extra_css_modules: for profile in self.opts.output_profile.extra_css_modules:
cssutils.profile.addProfile(profile['name'], cssprofiles.addProfile(profile['name'],
profile['props'], profile['props'],
profile['macros']) profile['macros'])
parser = cssutils.CSSParser(fetcher=self._fetch_css_file, parser = CSSParser(fetcher=self._fetch_css_file,
log=logging.getLogger('calibre.css')) log=logging.getLogger('calibre.css'))
self.font_face_rules = [] self.font_face_rules = []
for elem in head: for elem in head:
@ -473,6 +473,7 @@ class Style(object):
self._width = None self._width = None
self._height = None self._height = None
self._lineHeight = None self._lineHeight = None
self._bgcolor = None
stylizer._styles[element] = self stylizer._styles[element] = self
def set(self, prop, val): def set(self, prop, val):
@ -533,6 +534,48 @@ class Style(object):
def pt_to_px(self, value): def pt_to_px(self, value):
return (self._profile.dpi / 72.0) * 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 @property
def fontSize(self): def fontSize(self):
def normalize_fontsize(value, base): def normalize_fontsize(value, base):

View File

@ -287,6 +287,18 @@ class ChooseLibraryAction(InterfaceAction):
'rate of approximately 1 book every three seconds.'), show=True) 'rate of approximately 1 book every three seconds.'), show=True)
def restore_database(self): 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 from calibre.gui2.dialogs.restore_library import restore_database
m = self.gui.library_view.model() m = self.gui.library_view.model()
m.stop_metadata_backup() m.stop_metadata_backup()

View File

@ -388,6 +388,10 @@ class MetadataSingleDialogBase(ResizableDialog):
def apply_changes(self): def apply_changes(self):
self.changed.add(self.book_id) 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: for widget in self.basic_metadata_widgets:
try: try:
if not widget.commit(self.db, self.book_id): if not widget.commit(self.db, self.book_id):

View File

@ -21,8 +21,8 @@ NS = 'http://calibre-ebook.com/recipe_collection'
E = ElementMaker(namespace=NS, nsmap={None:NS}) E = ElementMaker(namespace=NS, nsmap={None:NS})
def iterate_over_builtin_recipe_files(): def iterate_over_builtin_recipe_files():
exclude = ['craigslist', 'iht', 'outlook_india', 'toronto_sun', exclude = ['craigslist', 'iht', 'toronto_sun',
'indian_express', 'india_today', 'livemint'] 'india_today', 'livemint']
d = os.path.dirname d = os.path.dirname
base = os.path.join(d(d(d(d(d(d(os.path.abspath(__file__))))))), 'recipes') base = os.path.join(d(d(d(d(d(d(os.path.abspath(__file__))))))), 'recipes')
for f in os.listdir(base): for f in os.listdir(base):