diff --git a/src/calibre/devices/apple/driver.py b/src/calibre/devices/apple/driver.py index 76ecce3a8e..48e078c47d 100644 --- a/src/calibre/devices/apple/driver.py +++ b/src/calibre/devices/apple/driver.py @@ -9,7 +9,7 @@ import cStringIO, ctypes, datetime, os, re, shutil, subprocess, sys, tempfile, t from calibre.constants import __appname__, __version__, DEBUG from calibre import fit_image from calibre.constants import isosx, iswindows -from calibre.devices.errors import UserFeedback +from calibre.devices.errors import OpenFeedback, UserFeedback from calibre.devices.usbms.deviceconfig import DeviceConfig from calibre.devices.interface import DevicePlugin from calibre.ebooks.BeautifulSoup import BeautifulSoup @@ -23,6 +23,7 @@ from calibre.utils.date import now, parse_date from calibre.utils.logging import Log from calibre.utils.zipfile import ZipFile + from PIL import Image as PILImage from lxml import etree @@ -41,7 +42,29 @@ class DriverBase(DeviceConfig, DevicePlugin): # Needed for config_widget to work FORMATS = ['epub', 'pdf'] USER_CAN_ADD_NEW_FORMATS = False - SUPPORTS_SUB_DIRS = True # To enable second checkbox in customize widget + + # Hide the standard customization widgets + SUPPORTS_SUB_DIRS = False + MUST_READ_METADATA = True + SUPPORTS_USE_AUTHOR_SORT = False + + EXTRA_CUSTOMIZATION_MESSAGE = [ + _('Use Series as Category in iTunes/iBooks') + + ':::'+_('Enable to use the series name as the iTunes Genre, ' + 'iBooks Category'), + _('Cache covers from iTunes/iBooks') + + ':::' + + _('Enable to cache and display covers from iTunes/iBooks'), + _("Skip 'Connect to iTunes' recommendation") + + ':::' + + _("Enable to skip the 'Connect to iTunes' recommendation dialog") + ] + EXTRA_CUSTOMIZATION_DEFAULT = [ + True, + True, + False, + ] + @classmethod def _config_base_name(cls): @@ -97,6 +120,11 @@ class ITUNES(DriverBase): #: The version of this plugin as a 3-tuple (major, minor, revision) version = (0,9,0) + # EXTRA_CUSTOMIZATION_MESSAGE indexes + USE_SERIES_AS_CATEGORY = 0 + CACHE_COVERS = 1 + SKIP_CONNECT_TO_ITUNES_DIALOG = 2 + OPEN_FEEDBACK_MESSAGE = _( 'Apple device detected, launching iTunes, please wait ...') BACKLOADING_ERROR_MESSAGE = _( @@ -295,7 +323,7 @@ class ITUNES(DriverBase): if not oncard: if DEBUG: self.log.info("ITUNES:books():") - if self.settings().use_subdirs: + if self.settings().extra_customization[self.CACHE_COVERS]: self.log.info(" Cover fetching/caching enabled") else: self.log.info(" Cover fetching/caching disabled") @@ -718,6 +746,14 @@ class ITUNES(DriverBase): if DEBUG: self.log.info("ITUNES.open()") + # Display a dialog recommending using 'Connect to iTunes' + if not self.settings().extra_customization[self.SKIP_CONNECT_TO_ITUNES_DIALOG]: + raise OpenFeedback("The recommended connection method for Apple iDevices " +\ + "is to use the 'Connect to iTunes' method described in the
" +\ + 'Calibre + Apple iDevices FAQ.
' +\ + 'After following the Quick Start steps outlined in the FAQ, restart calibre.') + + # Confirm/create thumbs archive if not os.path.exists(self.cache_dir): if DEBUG: @@ -1787,9 +1823,7 @@ class ITUNES(DriverBase): as of iTunes 9.2, iBooks 1.1, can't set artwork for PDF files via automation ''' - # self.settings().use_subdirs is a repurposed DeviceConfig field - # We're using it to skip fetching/caching covers to speed things up - if not self.settings().use_subdirs: + if not self.settings().extra_customization[self.CACHE_COVERS]: thumb_data = None return thumb_data @@ -2673,8 +2707,7 @@ class ITUNES(DriverBase): # Set genre from series if available, else first alpha tag # Otherwise iTunes grabs the first dc:subject from the opf metadata - # self.settings().read_metadata is used as a surrogate for "Use Series name as Genre" - if metadata_x.series and self.settings().read_metadata: + if metadata_x.series and self.settings().extra_customization[self.USE_SERIES_AS_CATEGORY]: if DEBUG: self.log.info(" ITUNES._update_iTunes_metadata()") self.log.info(" using Series name as Genre") @@ -2716,7 +2749,7 @@ class ITUNES(DriverBase): elif metadata_x.tags is not None: if DEBUG: self.log.info(" %susing Tag as Genre" % - "no Series name available, " if self.settings().read_metadata else '') + "no Series name available, " if self.settings().extra_customization[self.USE_SERIES_AS_CATEGORY] else '') for tag in metadata_x.tags: if self._is_alpha(tag[0]): if lb_added: @@ -2768,7 +2801,7 @@ class ITUNES(DriverBase): # Otherwise iBooks uses first from opf # iTunes balks on setting EpisodeNumber, but it sticks (9.1.1.12) - if metadata_x.series and self.settings().read_metadata: + if metadata_x.series and self.settings().extra_customization[self.USE_SERIES_AS_CATEGORY]: if DEBUG: self.log.info(" using Series name as Genre") # Format the index as a sort key @@ -2927,7 +2960,7 @@ class ITUNES_ASYNC(ITUNES): if not oncard: if DEBUG: self.log.info("ITUNES_ASYNC:books()") - if self.settings().use_subdirs: + if self.settings().extra_customization[self.CACHE_COVERS]: self.log.info(" Cover fetching/caching enabled") else: self.log.info(" Cover fetching/caching disabled") @@ -3075,6 +3108,38 @@ class ITUNES_ASYNC(ITUNES): only_presence=False): return self.connected, self + def open(self, library_uuid): + ''' + Perform any device specific initialization. Called after the device is + detected but before any other functions that communicate with the device. + For example: For devices that present themselves as USB Mass storage + devices, this method would be responsible for mounting the device or + if the device has been automounted, for finding out where it has been + mounted. The base class within USBMS device.py has a implementation of + this function that should serve as a good example for USB Mass storage + devices. + + Note that most of the initialization is necessarily performed in can_handle(), as + we need to talk to iTunes to discover if there's a connected iPod + ''' + if DEBUG: + self.log.info("ITUNES_ASYNC.open()") + + # Confirm/create thumbs archive + if not os.path.exists(self.cache_dir): + if DEBUG: + self.log.info(" creating thumb cache '%s'" % self.cache_dir) + os.makedirs(self.cache_dir) + + if not os.path.exists(self.archive_path): + self.log.info(" creating zip archive") + zfw = ZipFile(self.archive_path, mode='w') + zfw.writestr("iTunes Thumbs Archive",'') + zfw.close() + else: + if DEBUG: + self.log.info(" existing thumb cache at '%s'" % self.archive_path) + def sync_booklists(self, booklists, end_session=True): ''' Update metadata on device.