merge from trunk

This commit is contained in:
Charles Haley 2010-06-27 12:15:59 +01:00
commit 814ece6980
13 changed files with 3254 additions and 26 deletions

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 105 KiB

View File

@ -453,7 +453,7 @@ from calibre.devices.hanvon.driver import N516, EB511, ALEX, AZBOOKA, THEBOOK
from calibre.devices.edge.driver import EDGE from calibre.devices.edge.driver import EDGE
from calibre.devices.teclast.driver import TECLAST_K3, NEWSMY, IPAPYRUS from calibre.devices.teclast.driver import TECLAST_K3, NEWSMY, IPAPYRUS
from calibre.devices.sne.driver import SNE from calibre.devices.sne.driver import SNE
from calibre.devices.misc import PALMPRE, AVANT from calibre.devices.misc import PALMPRE, AVANT, SWEEX
from calibre.devices.folder_device.driver import FOLDER_DEVICE_FOR_CONFIG from calibre.devices.folder_device.driver import FOLDER_DEVICE_FOR_CONFIG
from calibre.devices.kobo.driver import KOBO from calibre.devices.kobo.driver import KOBO
@ -499,7 +499,6 @@ plugins += [
] ]
# Order here matters. The first matched device is the one used. # Order here matters. The first matched device is the one used.
plugins += [ plugins += [
ITUNES,
HANLINV3, HANLINV3,
HANLINV5, HANLINV5,
BLACKBERRY, BLACKBERRY,
@ -551,6 +550,8 @@ plugins += [
FOLDER_DEVICE_FOR_CONFIG, FOLDER_DEVICE_FOR_CONFIG,
AVANT, AVANT,
MENTOR, MENTOR,
SWEEX,
ITUNES,
] ]
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \ plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
x.__name__.endswith('MetadataReader')] x.__name__.endswith('MetadataReader')]

View File

@ -49,3 +49,23 @@ class AVANT(USBMS):
EBOOK_DIR_MAIN = '' EBOOK_DIR_MAIN = ''
SUPPORTS_SUB_DIRS = True SUPPORTS_SUB_DIRS = True
class SWEEX(USBMS):
name = 'Sweex Device Interface'
gui_name = 'Sweex'
description = _('Communicate with the Sweex MM300')
author = 'Kovid Goyal'
supported_platforms = ['windows', 'osx', 'linux']
# Ordered list of supported formats
FORMATS = ['epub', 'prc', 'fb2', 'html', 'rtf', 'chm', 'pdf', 'txt']
VENDOR_ID = [0x0525]
PRODUCT_ID = [0xa4a5]
BCD = [0x0319]
VENDOR_NAME = 'SWEEX'
WINDOWS_MAIN_MEM = WINDOWS_CARD_A_MEM = 'EBOOKREADER'
EBOOK_DIR_MAIN = ''
SUPPORTS_SUB_DIRS = True

View File

@ -273,6 +273,7 @@ def filter_metadata_results(item):
def do_cover_check(item): def do_cover_check(item):
item.has_cover = False item.has_cover = False
if item.isbn:
try: try:
item.has_cover = check_for_cover(item.isbn) item.has_cover = check_for_cover(item.isbn)
except: except:

View File

@ -34,7 +34,8 @@ def fetch_metadata(url, max=100, timeout=5.):
errmsg = soup.find('errormessage').string errmsg = soup.find('errormessage').string
raise ISBNDBError('Error fetching metadata: '+errmsg) raise ISBNDBError('Error fetching metadata: '+errmsg)
total_results = int(book_list['total_results']) total_results = int(book_list['total_results'])
np = '&page_number=%s&'%(page_number+1) page_number += 1
np = '&page_number=%s&'%page_number
url = re.sub(r'\&page_number=\d+\&', np, url) url = re.sub(r'\&page_number=\d+\&', np, url)
books.extend(book_list.findAll('bookdata')) books.extend(book_list.findAll('bookdata'))
max -= 1 max -= 1

View File

@ -7,7 +7,7 @@ __license__ = 'GPL v3'
__copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>' __copyright__ = '2008, Marshall T. Vandegrift <llasram@gmail.com>'
__docformat__ = 'restructuredtext en' __docformat__ = 'restructuredtext en'
import os, re, uuid, logging, functools import os, re, uuid, logging
from mimetypes import types_map from mimetypes import types_map
from collections import defaultdict from collections import defaultdict
from itertools import count from itertools import count
@ -808,17 +808,17 @@ class Manifest(object):
pat = re.compile(r'&(%s);'%('|'.join(user_entities.keys()))) pat = re.compile(r'&(%s);'%('|'.join(user_entities.keys())))
data = pat.sub(lambda m:user_entities[m.group(1)], data) data = pat.sub(lambda m:user_entities[m.group(1)], data)
fromstring = functools.partial(etree.fromstring, parser=RECOVER_PARSER) parser = etree.XMLParser(no_network=True, huge_tree=True)
# Try with more & more drastic measures to parse # Try with more & more drastic measures to parse
def first_pass(data): def first_pass(data):
try: try:
data = fromstring(data) data = etree.fromstring(data, parser=parser)
except etree.XMLSyntaxError, err: except etree.XMLSyntaxError, err:
self.oeb.log.exception('Initial parse failed:') self.oeb.log.exception('Initial parse failed:')
repl = lambda m: ENTITYDEFS.get(m.group(1), m.group(0)) repl = lambda m: ENTITYDEFS.get(m.group(1), m.group(0))
data = ENTITY_RE.sub(repl, data) data = ENTITY_RE.sub(repl, data)
try: try:
data = fromstring(data) data = etree.fromstring(data, parser=parser)
except etree.XMLSyntaxError, err: except etree.XMLSyntaxError, err:
self.oeb.logger.warn('Parsing file %r as HTML' % self.href) self.oeb.logger.warn('Parsing file %r as HTML' % self.href)
if err.args and err.args[0].startswith('Excessive depth'): if err.args and err.args[0].startswith('Excessive depth'):
@ -832,9 +832,9 @@ class Manifest(object):
elem.text = elem.text.strip('-') elem.text = elem.text.strip('-')
data = etree.tostring(data, encoding=unicode) data = etree.tostring(data, encoding=unicode)
try: try:
data = fromstring(data) data = etree.fromstring(data, parser=parser)
except etree.XMLSyntaxError: except etree.XMLSyntaxError:
data = fromstring(data) data = etree.fromstring(data, parser=RECOVER_PARSER)
return data return data
data = first_pass(data) data = first_pass(data)
@ -866,12 +866,12 @@ class Manifest(object):
data = etree.tostring(data, encoding=unicode) data = etree.tostring(data, encoding=unicode)
try: try:
data = fromstring(data) data = etree.fromstring(data, parser=parser)
except: except:
data = data.replace(':=', '=').replace(':>', '>') data = data.replace(':=', '=').replace(':>', '>')
data = data.replace('<http:/>', '') data = data.replace('<http:/>', '')
try: try:
data = fromstring(data) data = etree.fromstring(data, parser=parser)
except etree.XMLSyntaxError: except etree.XMLSyntaxError:
self.oeb.logger.warn('Stripping comments and meta tags from %s'% self.oeb.logger.warn('Stripping comments and meta tags from %s'%
self.href) self.href)
@ -882,7 +882,7 @@ class Manifest(object):
"<?xml version='1.0' encoding='utf-8'?><o:p></o:p>", "<?xml version='1.0' encoding='utf-8'?><o:p></o:p>",
'') '')
data = data.replace("<?xml version='1.0' encoding='utf-8'??>", '') data = data.replace("<?xml version='1.0' encoding='utf-8'??>", '')
data = fromstring(data) data = etree.fromstring(data)
elif namespace(data.tag) != XHTML_NS: elif namespace(data.tag) != XHTML_NS:
# OEB_DOC_NS, but possibly others # OEB_DOC_NS, but possibly others
ns = namespace(data.tag) ns = namespace(data.tag)

View File

@ -248,7 +248,7 @@ def info_dialog(parent, title, msg, det_msg='', show=False):
class Dispatcher(QObject): class Dispatcher(QObject):
'''Convenience class to ensure that a function call always happens in the '''Convenience class to ensure that a function call always happens in the
thread the reciver was created in.''' thread the receiver was created in.'''
dispatch_signal = pyqtSignal(object, object) dispatch_signal = pyqtSignal(object, object)
def __init__(self, func): def __init__(self, func):
@ -507,7 +507,7 @@ def pixmap_to_data(pixmap, format='JPEG'):
buf = QBuffer(ba) buf = QBuffer(ba)
buf.open(QBuffer.WriteOnly) buf.open(QBuffer.WriteOnly)
pixmap.save(buf, format) pixmap.save(buf, format)
return str(ba.data()) return bytes(ba.data())
class ResizableDialog(QDialog): class ResizableDialog(QDialog):

View File

@ -90,7 +90,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
COVER_FETCH_TIMEOUT = 240 # seconds COVER_FETCH_TIMEOUT = 240 # seconds
def do_reset_cover(self, *args): def do_reset_cover(self, *args):
pix = QPixmap(I('book.svg')) pix = QPixmap(I('default_cover.svg'))
self.cover.setPixmap(pix) self.cover.setPixmap(pix)
self.cover_changed = True self.cover_changed = True
self.cover_data = None self.cover_data = None
@ -408,7 +408,7 @@ class MetadataSingleDialog(ResizableDialog, Ui_MetadataSingleDialog):
if cover: if cover:
pm.loadFromData(cover) pm.loadFromData(cover)
if pm.isNull(): if pm.isNull():
pm = QPixmap(I('book.svg')) pm = QPixmap(I('default_cover.svg'))
else: else:
self.cover_data = cover self.cover_data = cover
self.cover.setPixmap(pm) self.cover.setPixmap(pm)

View File

@ -56,7 +56,8 @@ class ToolbarMixin(object): # {{{
partial(self.edit_metadata, False, bulk=True)) partial(self.edit_metadata, False, bulk=True))
md.addSeparator() md.addSeparator()
md.addAction(_('Download metadata and covers'), md.addAction(_('Download metadata and covers'),
partial(self.download_metadata, False, covers=True)) partial(self.download_metadata, False, covers=True),
Qt.ControlModifier+Qt.Key_D)
md.addAction(_('Download only metadata'), md.addAction(_('Download only metadata'),
partial(self.download_metadata, False, covers=False)) partial(self.download_metadata, False, covers=False))
md.addAction(_('Download only covers'), md.addAction(_('Download only covers'),

View File

@ -43,6 +43,14 @@ class FormatPath(unicode):
ans.deleted_after_upload = False ans.deleted_after_upload = False
return ans return ans
_default_image = None
def default_image():
global _default_image
if _default_image is None:
_default_image = QImage(I('default_cover.svg'))
return _default_image
class BooksModel(QAbstractTableModel): # {{{ class BooksModel(QAbstractTableModel): # {{{
about_to_be_sorted = pyqtSignal(object, name='aboutToBeSorted') about_to_be_sorted = pyqtSignal(object, name='aboutToBeSorted')
@ -71,7 +79,7 @@ class BooksModel(QAbstractTableModel): # {{{
self.book_on_device = None self.book_on_device = None
self.editable_cols = ['title', 'authors', 'rating', 'publisher', self.editable_cols = ['title', 'authors', 'rating', 'publisher',
'tags', 'series', 'timestamp', 'pubdate'] 'tags', 'series', 'timestamp', 'pubdate']
self.default_image = QImage(I('book.svg')) self.default_image = default_image()
self.sorted_on = DEFAULT_SORT self.sorted_on = DEFAULT_SORT
self.sort_history = [self.sorted_on] self.sort_history = [self.sorted_on]
self.last_search = '' # The last search performed on this model self.last_search = '' # The last search performed on this model

View File

@ -56,6 +56,8 @@ def init_qt(args):
def get_default_library_path(): def get_default_library_path():
fname = _('Calibre Library') fname = _('Calibre Library')
if iswindows:
fname = 'Calibre Library'
if isinstance(fname, unicode): if isinstance(fname, unicode):
try: try:
fname = fname.encode(filesystem_encoding) fname = fname.encode(filesystem_encoding)

View File

@ -579,7 +579,7 @@ void PictureFlowPrivate::resetSlides()
static QImage prepareSurface(QImage img, int w, int h) static QImage prepareSurface(QImage img, int w, int h)
{ {
Qt::TransformationMode mode = Qt::SmoothTransformation; Qt::TransformationMode mode = Qt::SmoothTransformation;
img = img.scaled(w, h, Qt::KeepAspectRatioByExpanding, mode); img = img.scaled(w, h, Qt::IgnoreAspectRatio, mode);
// slightly larger, to accommodate for the reflection // slightly larger, to accommodate for the reflection
int hs = int(h * REFLECTION_FACTOR); int hs = int(h * REFLECTION_FACTOR);

View File

@ -539,17 +539,20 @@ MIME = '''\
</mime-info> </mime-info>
''' '''
def render_svg(image, dest): def render_svg(image, dest, width=128, height=128):
from PyQt4.QtGui import QPainter, QImage from PyQt4.QtGui import QPainter, QImage
from PyQt4.QtSvg import QSvgRenderer from PyQt4.QtSvg import QSvgRenderer
svg = QSvgRenderer(image.readAll()) image = image.readAll() if hasattr(image, 'readAll') else image
svg = QSvgRenderer(image)
painter = QPainter() painter = QPainter()
image = QImage(128,128,QImage.Format_ARGB32_Premultiplied) image = QImage(width, height, QImage.Format_ARGB32)
painter.begin(image) painter.begin(image)
painter.setRenderHints(QPainter.Antialiasing|QPainter.TextAntialiasing|QPainter.SmoothPixmapTransform|QPainter.HighQualityAntialiasing) painter.setRenderHints(QPainter.Antialiasing|QPainter.TextAntialiasing|QPainter.SmoothPixmapTransform|QPainter.HighQualityAntialiasing)
painter.setCompositionMode(QPainter.CompositionMode_SourceOver) painter.setCompositionMode(QPainter.CompositionMode_SourceOver)
svg.render(painter) svg.render(painter)
painter.end() painter.end()
if dest is None:
return image
image.save(dest) image.save(dest)
def main(): def main():