From Greg

This commit is contained in:
Charles Haley 2011-04-18 08:34:22 +01:00
parent bd3b770297
commit 4ea961ba62
8 changed files with 154 additions and 28 deletions

View File

@ -582,6 +582,7 @@ from calibre.ebooks.snb.output import SNBOutput
from calibre.customize.profiles import input_profiles, output_profiles
from calibre.devices.apple.driver import ITUNES
from calibre.devices.content_server.driver import CONTENT_SERVER_FOR_CONFIG
from calibre.devices.hanlin.driver import HANLINV3, HANLINV5, BOOX, SPECTRA
from calibre.devices.blackberry.driver import BLACKBERRY
from calibre.devices.cybook.driver import CYBOOK, ORIZON
@ -753,7 +754,9 @@ plugins += [
EEEREADER,
NEXTBOOK,
ITUNES,
]
CONTENT_SERVER_FOR_CONFIG
]
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \
x.__name__.endswith('MetadataReader')]
plugins += [x for x in list(locals().values()) if isinstance(x, type) and \

View File

@ -201,8 +201,9 @@ class ITUNES(DriverBase):
# 0x1294 iPhone 3GS
# 0x1297 iPhone 4
# 0x129a iPad
# 0x12a2 iPad2
VENDOR_ID = [0x05ac]
PRODUCT_ID = [0x1292,0x1293,0x1294,0x1297,0x1299,0x129a]
PRODUCT_ID = [0x1292,0x1293,0x1294,0x1297,0x1299,0x129a,0x12a2]
BCD = [0x01]
# Plugboard ID
@ -421,7 +422,7 @@ class ITUNES(DriverBase):
cached_books[this_book.path] = {
'title':book.name(),
'author':[book.artist()],
'author':book.artist().split(' & '),
'lib_book':library_books[this_book.path] if this_book.path in library_books else None,
'dev_book':book,
'uuid': book.composer()
@ -459,7 +460,7 @@ class ITUNES(DriverBase):
cached_books[this_book.path] = {
'title':book.Name,
'author':book.Artist,
'author':book.artist().split(' & '),
'lib_book':library_books[this_book.path] if this_book.path in library_books else None,
'uuid': book.Composer,
'format': 'pdf' if book.KindAsString.startswith('PDF') else 'epub'
@ -1021,7 +1022,9 @@ class ITUNES(DriverBase):
if isosx:
for (i,file) in enumerate(files):
format = file.rpartition('.')[2].lower()
path = self.path_template % (metadata[i].title, metadata[i].author[0],format)
path = self.path_template % (metadata[i].title,
authors_to_string(metadata[i].authors),
format)
self._remove_existing_copy(path, metadata[i])
fpath = self._get_fpath(file, metadata[i], format, update_md=True)
db_added, lb_added = self._add_new_copy(fpath, metadata[i])
@ -1034,9 +1037,11 @@ class ITUNES(DriverBase):
if DEBUG:
self.log.info("ITUNES.upload_books()")
self.log.info(" adding '%s' by '%s' uuid:%s to self.cached_books" %
( metadata[i].title, metadata[i].author, metadata[i].uuid))
(metadata[i].title,
authors_to_string(metadata[i].authors),
metadata[i].uuid))
self.cached_books[this_book.path] = {
'author': metadata[i].author,
'author': authors_to_string(metadata[i].authors),
'dev_book': db_added,
'format': format,
'lib_book': lb_added,
@ -1055,7 +1060,9 @@ class ITUNES(DriverBase):
for (i,file) in enumerate(files):
format = file.rpartition('.')[2].lower()
path = self.path_template % (metadata[i].title, metadata[i].author[0],format)
path = self.path_template % (metadata[i].title,
authors_to_string(metadata[i].authors),
format)
self._remove_existing_copy(path, metadata[i])
fpath = self._get_fpath(file, metadata[i],format, update_md=True)
db_added, lb_added = self._add_new_copy(fpath, metadata[i])
@ -1075,9 +1082,11 @@ class ITUNES(DriverBase):
if DEBUG:
self.log.info("ITUNES.upload_books()")
self.log.info(" adding '%s' by '%s' uuid:%s to self.cached_books" %
( metadata[i].title, metadata[i].author, metadata[i].uuid))
(metadata[i].title,
authors_to_string(metadata[i].authors),
metadata[i].uuid))
self.cached_books[this_book.path] = {
'author': metadata[i].author[0],
'author': authors_to_string(metadata[i].authors),
'dev_book': db_added,
'format': format,
'lib_book': lb_added,
@ -1190,7 +1199,7 @@ class ITUNES(DriverBase):
base_fn = base_fn.rpartition('.')[0]
db_added = self._find_device_book(
{ 'title': base_fn if format == 'pdf' else metadata.title,
'author': metadata.authors[0],
'author': authors_to_string(metadata.authors),
'uuid': metadata.uuid,
'format': format})
return db_added
@ -1255,7 +1264,7 @@ class ITUNES(DriverBase):
base_fn = base_fn.rpartition('.')[0]
added = self._find_library_book(
{ 'title': base_fn if format == 'pdf' else metadata.title,
'author': metadata.author[0],
'author': authors_to_string(metadata.authors),
'uuid': metadata.uuid,
'format': format})
return added
@ -1314,7 +1323,7 @@ class ITUNES(DriverBase):
with open(metadata.cover,'r+b') as cd:
cover_data = cd.read()
except:
self.problem_titles.append("'%s' by %s" % (metadata.title, metadata.author[0]))
self.problem_titles.append("'%s' by %s" % (metadata.title, authors_to_string(metadata.authors)))
self.log.error(" error scaling '%s' for '%s'" % (metadata.cover,metadata.title))
import traceback
@ -1389,7 +1398,7 @@ class ITUNES(DriverBase):
thumb_path = path.rpartition('.')[0] + '.jpg'
zfw.writestr(thumb_path, thumb)
except:
self.problem_titles.append("'%s' by %s" % (metadata.title, metadata.author[0]))
self.problem_titles.append("'%s' by %s" % (metadata.title, authors_to_string(metadata.authors)))
self.log.error(" error converting '%s' to thumb for '%s'" % (metadata.cover,metadata.title))
finally:
try:
@ -1407,7 +1416,7 @@ class ITUNES(DriverBase):
if DEBUG:
self.log.info(" ITUNES._create_new_book()")
this_book = Book(metadata.title, authors_to_string(metadata.author))
this_book = Book(metadata.title, authors_to_string(metadata.authors))
this_book.datetime = time.gmtime()
this_book.db_id = None
this_book.device_collections = []
@ -2451,7 +2460,7 @@ class ITUNES(DriverBase):
for book in self.cached_books:
if self.cached_books[book]['uuid'] == metadata.uuid or \
(self.cached_books[book]['title'] == metadata.title and \
self.cached_books[book]['author'] == metadata.authors[0]):
self.cached_books[book]['author'] == authors_to_string(metadata.authors)):
self.update_list.append(self.cached_books[book])
self._remove_from_device(self.cached_books[book])
if DEBUG:
@ -2470,7 +2479,7 @@ class ITUNES(DriverBase):
for book in self.cached_books:
if self.cached_books[book]['uuid'] == metadata.uuid or \
(self.cached_books[book]['title'] == metadata.title and \
self.cached_books[book]['author'] == metadata.authors[0]):
self.cached_books[book]['author'] == authors_to_string(metadata.authors)):
self.update_list.append(self.cached_books[book])
self._remove_from_iTunes(self.cached_books[book])
if DEBUG:
@ -2939,13 +2948,13 @@ class ITUNES(DriverBase):
def _xform_metadata_via_plugboard(self, book, format):
''' Transform book metadata from plugboard templates '''
if DEBUG:
self.log.info(" ITUNES._xform_metadata_via_plugboard()")
self.log.info(" ITUNES._xform_metadata_via_plugboard()")
if self.plugboard_func:
pb = self.plugboard_func(self.DEVICE_PLUGBOARD_NAME, format, self.plugboards)
newmi = book.deepcopy_metadata()
newmi.template_to_attribute(book, pb)
if DEBUG:
if pb is not None and DEBUG:
self.log.info(" transforming %s using %s:" % (format, pb))
self.log.info(" title: %s %s" % (book.title, ">>> %s" %
newmi.title if book.title != newmi.title else ''))
@ -3062,7 +3071,7 @@ class ITUNES_ASYNC(ITUNES):
cached_books[this_book.path] = {
'title':library_books[book].name(),
'author':[library_books[book].artist()],
'author':library_books[book].artist().split(' & '),
'lib_book':library_books[book],
'dev_book':None,
'uuid': library_books[book].composer(),
@ -3102,7 +3111,7 @@ class ITUNES_ASYNC(ITUNES):
cached_books[this_book.path] = {
'title':library_books[book].Name,
'author':library_books[book].Artist,
'author':library_books[book].Artist.split(' & '),
'lib_book':library_books[book],
'uuid': library_books[book].Composer,
'format': format
@ -3288,7 +3297,7 @@ class Book(Metadata):
See ebooks.metadata.book.base
'''
def __init__(self,title,author):
Metadata.__init__(self, title, authors=[author])
Metadata.__init__(self, title, authors=author.split(' & '))
@property
def title_sorter(self):

View File

@ -0,0 +1,10 @@
#!/usr/bin/env python
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
from __future__ import with_statement
__license__ = 'GPL v3'
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
__docformat__ = 'restructuredtext en'

View File

@ -0,0 +1,74 @@
'''
Created on 17 Apr 2011
@author: GRiker, modeled on charles's Folder Device
'''
from calibre.constants import DEBUG
from calibre.devices.interface import DevicePlugin
from calibre.devices.usbms.deviceconfig import DeviceConfig
from calibre.devices.usbms.driver import USBMS, BookList
class DriverBase(DeviceConfig, DevicePlugin):
# Reduce to just the formats eligible for plugboard xforms
# These formats are shown in the customization dialog
FORMATS = ['epub', 'mobi']
USER_CAN_ADD_NEW_FORMATS = False
# Hide the standard customization widgets
SUPPORTS_SUB_DIRS = False
MUST_READ_METADATA = True
SUPPORTS_USE_AUTHOR_SORT = False
# This class is added to the standard device plugin chain, so that it can
# be configured. It has invalid vendor_id etc, so it will never match a
# device. The 'real' CONTENT_SERVER will use the config from it.
class CONTENT_SERVER_FOR_CONFIG(USBMS):
name = 'Content Server Interface'
gui_name = 'Content Server'
description = _('Enables metadata plugboards to be used with Content Server.')
author = 'GRiker'
supported_platforms = ['windows', 'osx', 'linux']
VENDOR_ID = [0xffff]
PRODUCT_ID = [0xffff]
BCD = [0xffff]
DEVICE_PLUGBOARD_NAME = 'CONTENT_SERVER'
def config_widget(cls):
'''
Configure a minimal QWidget
Better to simply disable the config_widget altogether
'''
cw = DriverBase.config_widget()
# Turn off the Save template
cw.opt_save_template.setVisible(False)
cw.label.setVisible(False)
# Hide the up/down arrows
cw.column_up.setVisible(False)
cw.column_down.setVisible(False)
# Retitle
cw.groupBox.setTitle(_("Enable metadata plugboards for the following formats:"))
return cw
class CONTENT_SERVER(USBMS):
FORMATS = CONTENT_SERVER_FOR_CONFIG.FORMATS
DEVICE_PLUGBOARD_NAME = 'CONTENT_SERVER'
def __init__(self):
if DEBUG:
print("CONTENT_SERVER.init()")
pass
def set_plugboards(self, plugboards, pb_func):
# This method is called with the plugboard that matches the format
# declared in use_plugboard_ext and a device name of CONTENT_SERVER
if DEBUG:
print("CONTENT_SERVER.set_plugboards()")
print(' using plugboard %s' % plugboards)
self.plugboards = plugboards
self.plugboard_func = pb_func

View File

@ -17,7 +17,7 @@ from calibre.gui2.actions import InterfaceAction
class GenerateCatalogAction(InterfaceAction):
name = 'Generate Catalog'
action_spec = (_('Create a catalog of the books in your calibre library'), None, None, None)
action_spec = (_('Create a catalog of the books in your calibre library'), 'catalog.png', 'Catalog builder', None)
dont_add_to = frozenset(['menubar-device', 'toolbar-device', 'context-menu-device'])
def generate_catalog(self):

View File

@ -892,7 +892,7 @@ class DeviceMixin(object): # {{{
sub_dest_parts.append('')
to = sub_dest_parts[0]
fmts = sub_dest_parts[1]
subject = ';'.join(sub_dest_parts[2:])
subject = ';'.join(sub_dest_parts[2:])
fmts = [x.strip().lower() for x in fmts.split(',')]
self.send_by_mail(to, fmts, delete, subject=subject)

View File

@ -12,6 +12,7 @@ from zipfile import ZipFile, ZIP_DEFLATED, ZIP_STORED
from PyQt4.Qt import QDialog
from calibre.constants import isosx, iswindows
from calibre.gui2 import open_local_file
from calibre.gui2.dialogs.tweak_epub_ui import Ui_Dialog
from calibre.libunzip import extract as zipextract
@ -42,11 +43,19 @@ class TweakEpub(QDialog, Ui_Dialog):
self.move(parent_loc.x(),parent_loc.y())
def cleanup(self):
if isosx:
try:
import appscript
self.finder = appscript.app('Finder')
self.finder.Finder_windows[os.path.basename(self._exploded)].close()
except:
# appscript fails to load on 10.4
pass
# Delete directory containing exploded ePub
if self._exploded is not None:
shutil.rmtree(self._exploded, ignore_errors=True)
def display_exploded(self):
'''
Generic subprocess launch of native file browser

View File

@ -183,16 +183,37 @@ class ContentServer(object):
if fmt is None:
raise cherrypy.HTTPError(404, 'book: %d does not have format: %s'%(id, format))
if format == 'EPUB':
# Get the original metadata
mi = self.db.get_metadata(id, index_is_id=True)
# Instantiate the CONTENT_SERVER driver
from calibre.devices.content_server.driver import CONTENT_SERVER
cs = CONTENT_SERVER()
# Get any EPUB plugboards for the content server
from calibre.gui2.device import find_plugboard, device_name_for_plugboards
plugboards = self.db.prefs.get('plugboards', {})
# Transform the metadata via the plugboard
if hasattr(cs, 'set_plugboards') and callable(cs.set_plugboards):
cs.set_plugboards(plugboards, find_plugboard)
cpb = find_plugboard(device_name_for_plugboards(cs), format.lower(), plugboards)
if cpb:
newmi = mi.deepcopy_metadata()
newmi.template_to_attribute(mi, cpb)
else:
newmi = mi
# Write the updated file
from tempfile import TemporaryFile
from calibre.ebooks.metadata.meta import set_metadata
raw = fmt.read()
fmt = TemporaryFile()
fmt.write(raw)
fmt.seek(0)
set_metadata(fmt, self.db.get_metadata(id, index_is_id=True,
get_cover=True),
'epub')
set_metadata(fmt, newmi, 'epub')
fmt.seek(0)
mt = guess_type('dummy.'+format.lower())[0]
if mt is None:
mt = 'application/octet-stream'