mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Improve logig for managing recipe orphans in auto-sync mode
This commit is contained in:
commit
47b7f8e822
@ -245,14 +245,13 @@ class ITUNES(DevicePlugin):
|
|||||||
|
|
||||||
# Fetch a list of books from iPod device connected to iTunes
|
# Fetch a list of books from iPod device connected to iTunes
|
||||||
|
|
||||||
# Fetch Library|Books
|
|
||||||
library_books = self._get_library_books()
|
|
||||||
|
|
||||||
if 'iPod' in self.sources:
|
if 'iPod' in self.sources:
|
||||||
booklist = BookList(self.log)
|
booklist = BookList(self.log)
|
||||||
cached_books = {}
|
cached_books = {}
|
||||||
|
|
||||||
if isosx:
|
if isosx:
|
||||||
|
library_books = self._get_library_books()
|
||||||
device_books = self._get_device_books()
|
device_books = self._get_device_books()
|
||||||
book_count = float(len(device_books))
|
book_count = float(len(device_books))
|
||||||
for (i,book) in enumerate(device_books):
|
for (i,book) in enumerate(device_books):
|
||||||
@ -288,6 +287,7 @@ class ITUNES(DevicePlugin):
|
|||||||
try:
|
try:
|
||||||
pythoncom.CoInitialize()
|
pythoncom.CoInitialize()
|
||||||
self.iTunes = win32com.client.Dispatch("iTunes.Application")
|
self.iTunes = win32com.client.Dispatch("iTunes.Application")
|
||||||
|
library_books = self._get_library_books()
|
||||||
device_books = self._get_device_books()
|
device_books = self._get_device_books()
|
||||||
book_count = float(len(device_books))
|
book_count = float(len(device_books))
|
||||||
for (i,book) in enumerate(device_books):
|
for (i,book) in enumerate(device_books):
|
||||||
@ -317,6 +317,7 @@ class ITUNES(DevicePlugin):
|
|||||||
if self.report_progress is not None:
|
if self.report_progress is not None:
|
||||||
self.report_progress(i+1/book_count,
|
self.report_progress(i+1/book_count,
|
||||||
_('%d of %d') % (i+1, book_count))
|
_('%d of %d') % (i+1, book_count))
|
||||||
|
self._purge_orphans(cached_books)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
pythoncom.CoUninitialize()
|
pythoncom.CoUninitialize()
|
||||||
@ -1673,6 +1674,7 @@ class ITUNES(DevicePlugin):
|
|||||||
def _get_library_books(self):
|
def _get_library_books(self):
|
||||||
'''
|
'''
|
||||||
Populate a dict of paths from iTunes Library|Books
|
Populate a dict of paths from iTunes Library|Books
|
||||||
|
Windows assumes pythoncom wrapper
|
||||||
'''
|
'''
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info("\n ITUNES._get_library_books()")
|
self.log.info("\n ITUNES._get_library_books()")
|
||||||
@ -1731,58 +1733,58 @@ class ITUNES(DevicePlugin):
|
|||||||
|
|
||||||
elif iswindows:
|
elif iswindows:
|
||||||
lib = None
|
lib = None
|
||||||
try:
|
# try:
|
||||||
pythoncom.CoInitialize()
|
# pythoncom.CoInitialize()
|
||||||
self.iTunes = win32com.client.Dispatch("iTunes.Application")
|
# self.iTunes = win32com.client.Dispatch("iTunes.Application")
|
||||||
for source in self.iTunes.sources:
|
for source in self.iTunes.sources:
|
||||||
if source.Kind == self.Sources.index('Library'):
|
if source.Kind == self.Sources.index('Library'):
|
||||||
lib = source
|
lib = source
|
||||||
self.log.info(" Library source: '%s' kind: %s" % (lib.Name, self.Sources[lib.Kind]))
|
self.log.info(" Library source: '%s' kind: %s" % (lib.Name, self.Sources[lib.Kind]))
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.log.error(" Library source not found")
|
self.log.error(" Library source not found")
|
||||||
|
|
||||||
if lib is not None:
|
if lib is not None:
|
||||||
lib_books = None
|
lib_books = None
|
||||||
if lib.Playlists is not None:
|
if lib.Playlists is not None:
|
||||||
for pl in lib.Playlists:
|
for pl in lib.Playlists:
|
||||||
if pl.Kind == self.PlaylistKind.index('User') and \
|
if pl.Kind == self.PlaylistKind.index('User') and \
|
||||||
pl.SpecialKind == self.PlaylistSpecialKind.index('Books'):
|
pl.SpecialKind == self.PlaylistSpecialKind.index('Books'):
|
||||||
if DEBUG:
|
|
||||||
self.log.info(" Books playlist: '%s'" % (pl.Name))
|
|
||||||
lib_books = pl.Tracks
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.error(" no Library|Books playlist found")
|
self.log.info(" Books playlist: '%s'" % (pl.Name))
|
||||||
|
lib_books = pl.Tracks
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.error(" no Library playlists found")
|
self.log.error(" no Library|Books playlist found")
|
||||||
|
else:
|
||||||
|
if DEBUG:
|
||||||
|
self.log.error(" no Library playlists found")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for book in lib_books:
|
for book in lib_books:
|
||||||
# This may need additional entries for international iTunes users
|
# This may need additional entries for international iTunes users
|
||||||
if book.KindAsString in ['MPEG audio file']:
|
if book.KindAsString in ['MPEG audio file']:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info(" ignoring %-30.30s of type '%s'" % (book.Name, book.KindAsString))
|
self.log.info(" ignoring %-30.30s of type '%s'" % (book.Name, book.KindAsString))
|
||||||
else:
|
else:
|
||||||
path = self.path_template % (book.Name, book.Artist)
|
path = self.path_template % (book.Name, book.Artist)
|
||||||
|
|
||||||
# Collect calibre orphans
|
# Collect calibre orphans
|
||||||
if book.Description.startswith(self.description_prefix):
|
if book.Description.startswith(self.description_prefix):
|
||||||
if not book.Location:
|
if not book.Location:
|
||||||
library_orphans[path] = book
|
library_orphans[path] = book
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info(" found calibre orphan '%s' in Library|Books" % book.Name)
|
self.log.info(" found calibre orphan '%s' in Library|Books" % book.Name)
|
||||||
|
|
||||||
library_books[path] = book
|
library_books[path] = book
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info(" adding %-30.30s [%s]" % (book.Name, book.KindAsString))
|
self.log.info(" adding %-30.30s [%s]" % (book.Name, book.KindAsString))
|
||||||
except:
|
except:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info(" no books in library")
|
self.log.info(" no books in library")
|
||||||
finally:
|
# finally:
|
||||||
pythoncom.CoUninitialize()
|
# pythoncom.CoUninitialize()
|
||||||
self.library_orphans = library_orphans
|
self.library_orphans = library_orphans
|
||||||
return library_books
|
return library_books
|
||||||
|
|
||||||
@ -1915,23 +1917,21 @@ class ITUNES(DevicePlugin):
|
|||||||
'''
|
'''
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info(" ITUNES._purge_orphans")
|
self.log.info(" ITUNES._purge_orphans")
|
||||||
|
#self.log.info(" cached_books:\n %s" % "\n ".join(cached_books.keys()))
|
||||||
|
|
||||||
orphan_paths = {}
|
orphan_paths = {}
|
||||||
if DEBUG:
|
|
||||||
self.log.info(" cached_books:\n %s" % "\n ".join(cached_books.keys()))
|
|
||||||
|
|
||||||
if isosx:
|
if isosx:
|
||||||
for orphan in self.library_orphans:
|
for orphan in self.library_orphans:
|
||||||
path = self.path_template % (self.library_orphans[orphan].name(),
|
path = self.path_template % (self.library_orphans[orphan].name(),
|
||||||
self.library_orphans[orphan].artist())
|
self.library_orphans[orphan].artist())
|
||||||
orphan_paths[path] = self.library_orphans[orphan]
|
orphan_paths[path] = self.library_orphans[orphan]
|
||||||
if DEBUG:
|
|
||||||
self.log.info(" orphan_paths:\n %s" % "\n ".join(orphan_paths.keys()))
|
|
||||||
|
|
||||||
# Scan orphan_paths for paths not found in cached_books
|
# Scan orphan_paths for paths not found in cached_books
|
||||||
for orphan in orphan_paths.keys():
|
for orphan in orphan_paths.keys():
|
||||||
if orphan not in cached_books:
|
if orphan not in cached_books:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info(" '%s' not found in cached_books, removing from iTunes" % orphan)
|
self.log.info(" '%s' not found on device, removing from iTunes" % orphan)
|
||||||
self.iTunes.delete(orphan_paths[orphan])
|
self.iTunes.delete(orphan_paths[orphan])
|
||||||
|
|
||||||
elif iswindows:
|
elif iswindows:
|
||||||
@ -1939,14 +1939,12 @@ class ITUNES(DevicePlugin):
|
|||||||
path = self.path_template % (self.library_orphans[orphan].Name,
|
path = self.path_template % (self.library_orphans[orphan].Name,
|
||||||
self.library_orphans[orphan].Artist)
|
self.library_orphans[orphan].Artist)
|
||||||
orphan_paths[path] = self.library_orphans[orphan]
|
orphan_paths[path] = self.library_orphans[orphan]
|
||||||
if DEBUG:
|
|
||||||
self.log.info(" orphan_paths:\n %s" % "\n ".join(orphan_paths.keys()))
|
|
||||||
|
|
||||||
# Scan orphan_paths for paths not found in cached_books
|
# Scan orphan_paths for paths not found in cached_books
|
||||||
for orphan in orphan_paths.keys():
|
for orphan in orphan_paths.keys():
|
||||||
if orphan not in cached_books:
|
if orphan not in cached_books:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
self.log.info(" '%s' not found in cached_books, removing from iTunes" % orphan)
|
self.log.info(" '%s' not found on device, removing from iTunes" % orphan)
|
||||||
orphan_paths[orphan].Delete()
|
orphan_paths[orphan].Delete()
|
||||||
|
|
||||||
def _remove_existing_copies(self,path,file,metadata):
|
def _remove_existing_copies(self,path,file,metadata):
|
||||||
|
@ -47,7 +47,7 @@ class Book(MetaInformation):
|
|||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
# use lpath because the prefix can change, changing path
|
# use lpath because the prefix can change, changing path
|
||||||
return self.path == getattr(other, 'lpath', None)
|
return self.lpath == getattr(other, 'lpath', None)
|
||||||
|
|
||||||
@dynamic_property
|
@dynamic_property
|
||||||
def db_id(self):
|
def db_id(self):
|
||||||
|
@ -101,6 +101,11 @@ class Float(Int):
|
|||||||
w.setSpecialValueText(_('Undefined'))
|
w.setSpecialValueText(_('Undefined'))
|
||||||
w.setSingleStep(1)
|
w.setSingleStep(1)
|
||||||
|
|
||||||
|
def setter(self, val):
|
||||||
|
if val is None:
|
||||||
|
val = self.widgets[1].minimum()
|
||||||
|
self.widgets[1].setValue(val)
|
||||||
|
|
||||||
class Rating(Int):
|
class Rating(Int):
|
||||||
|
|
||||||
def setup_ui(self, parent):
|
def setup_ui(self, parent):
|
||||||
|
@ -229,9 +229,9 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
|
|||||||
self.connect(self.action_previous_page, SIGNAL('triggered(bool)'),
|
self.connect(self.action_previous_page, SIGNAL('triggered(bool)'),
|
||||||
lambda x:self.view.previous_page())
|
lambda x:self.view.previous_page())
|
||||||
self.connect(self.action_find_next, SIGNAL('triggered(bool)'),
|
self.connect(self.action_find_next, SIGNAL('triggered(bool)'),
|
||||||
lambda x:self.find(self.search.smart_text, True, repeat=True))
|
lambda x:self.find(self.search.smart_text, repeat=True))
|
||||||
self.connect(self.action_find_previous, SIGNAL('triggered(bool)'),
|
self.connect(self.action_find_previous, SIGNAL('triggered(bool)'),
|
||||||
lambda x:self.find(self.search.smart_text, True,
|
lambda x:self.find(self.search.smart_text,
|
||||||
repeat=True, backwards=True))
|
repeat=True, backwards=True))
|
||||||
|
|
||||||
self.connect(self.action_full_screen, SIGNAL('triggered(bool)'),
|
self.connect(self.action_full_screen, SIGNAL('triggered(bool)'),
|
||||||
|
@ -1304,12 +1304,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
|||||||
aid = self.conn.execute('INSERT INTO series(name) VALUES (?)', (series,)).lastrowid
|
aid = self.conn.execute('INSERT INTO series(name) VALUES (?)', (series,)).lastrowid
|
||||||
self.conn.execute('INSERT INTO books_series_link(book, series) VALUES (?,?)', (id, aid))
|
self.conn.execute('INSERT INTO books_series_link(book, series) VALUES (?,?)', (id, aid))
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
try:
|
|
||||||
row = self.row(id)
|
|
||||||
if row is not None:
|
|
||||||
self.data.set(row, 9, series)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
self.data.set(id, self.FIELD_MAP['series'], series, row_is_id=True)
|
self.data.set(id, self.FIELD_MAP['series'], series, row_is_id=True)
|
||||||
if notify:
|
if notify:
|
||||||
self.notify('metadata', [id])
|
self.notify('metadata', [id])
|
||||||
|
@ -159,7 +159,8 @@ Alternative for the iPad
|
|||||||
|
|
||||||
As of |app| version 0.7.0, you can plugin your iPad into the computer using its charging cable, and |app| will detect it and show you a list of books on the iPad. You can then use the Send to device button to send books directly to iBooks on the iPad.
|
As of |app| version 0.7.0, you can plugin your iPad into the computer using its charging cable, and |app| will detect it and show you a list of books on the iPad. You can then use the Send to device button to send books directly to iBooks on the iPad.
|
||||||
|
|
||||||
This method only works on Windows XP and higher and OS X 10.5 and higher. Linux is not supported (iTunes is not available in linux) and OS X 10.4 is not supported.
|
This method only works on Windows XP and higher and OS X 10.5 and higher. Linux is not supported (iTunes is not available in linux) and OS X 10.4 is not supported. For more details, see
|
||||||
|
`this forum post http://www.mobileread.com/forums/showpost.php?p=944079&postcount=1`_.
|
||||||
|
|
||||||
How do I use |app| with my Android phone?
|
How do I use |app| with my Android phone?
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Loading…
x
Reference in New Issue
Block a user