mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
cf8e89aed5
@ -85,6 +85,10 @@ class ISBNMerge(object):
|
||||
isbns, min_year = xisbn.get_isbn_pool(isbn)
|
||||
if not isbns:
|
||||
isbns = frozenset([isbn])
|
||||
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):
|
||||
|
@ -45,6 +45,11 @@ class xISBN(object):
|
||||
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,8 +62,7 @@ class xISBN(object):
|
||||
data = []
|
||||
id_ = len(self._data)
|
||||
self._data.append(data)
|
||||
for rec in data:
|
||||
for i in rec.get('isbn', []):
|
||||
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 @@ class MobiMLizer(object):
|
||||
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 @@ __copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
|
||||
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 @@ try:
|
||||
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 import unit_convert
|
||||
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 @@ class Stylizer(object):
|
||||
|
||||
# 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 @@ class Style(object):
|
||||
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 @@ class Style(object):
|
||||
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 @@ class ChooseLibraryAction(InterfaceAction):
|
||||
'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 @@ class MetadataSingleDialogBase(ResizableDialog):
|
||||
|
||||
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 @@ NS = 'http://calibre-ebook.com/recipe_collection'
|
||||
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…
x
Reference in New Issue
Block a user