mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
Pull from driver-dev
This commit is contained in:
commit
c60cd96dc5
@ -43,43 +43,13 @@ class CYBOOKG3(USBMS):
|
|||||||
|
|
||||||
def upload_books(self, files, names, on_card=None, end_session=True,
|
def upload_books(self, files, names, on_card=None, end_session=True,
|
||||||
metadata=None):
|
metadata=None):
|
||||||
if on_card == 'carda' and not self._card_a_prefix:
|
path = self._sanity_check(on_card, files)
|
||||||
raise ValueError(_('The reader has no storage card in this slot.'))
|
|
||||||
elif on_card == 'cardb' and not self._card_b_prefix:
|
|
||||||
raise ValueError(_('The reader has no storage card in this slot.'))
|
|
||||||
elif on_card and on_card not in ('carda', 'cardb'):
|
|
||||||
raise DeviceError(_('The reader has no storage card in this slot.'))
|
|
||||||
|
|
||||||
if on_card == 'carda':
|
|
||||||
path = os.path.join(self._card_a_prefix, self.EBOOK_DIR_CARD_A)
|
|
||||||
if on_card == 'cardb':
|
|
||||||
path = os.path.join(self._card_b_prefix, self.EBOOK_DIR_CARD_B)
|
|
||||||
else:
|
|
||||||
path = os.path.join(self._main_prefix, self.EBOOK_DIR_MAIN)
|
|
||||||
|
|
||||||
def get_size(obj):
|
|
||||||
if hasattr(obj, 'seek'):
|
|
||||||
obj.seek(0, os.SEEK_END)
|
|
||||||
size = obj.tell()
|
|
||||||
obj.seek(0)
|
|
||||||
return size
|
|
||||||
return os.path.getsize(obj)
|
|
||||||
|
|
||||||
sizes = [get_size(f) for f in files]
|
|
||||||
size = sum(sizes)
|
|
||||||
|
|
||||||
if not on_card and size > self.free_space()[0] - 2*1024*1024:
|
|
||||||
raise FreeSpaceError(_("There is insufficient free space in main memory"))
|
|
||||||
if on_card == 'carda' and size > self.free_space()[1] - 1024*1024:
|
|
||||||
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
|
|
||||||
if on_card == 'cardb' and size > self.free_space()[2] - 1024*1024:
|
|
||||||
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
|
|
||||||
|
|
||||||
paths = []
|
paths = []
|
||||||
names = iter(names)
|
names = iter(names)
|
||||||
metadata = iter(metadata)
|
metadata = iter(metadata)
|
||||||
|
|
||||||
for infile in files:
|
for i, infile in enumerate(files):
|
||||||
newpath = path
|
newpath = path
|
||||||
mdata = metadata.next()
|
mdata = metadata.next()
|
||||||
|
|
||||||
@ -90,7 +60,6 @@ class CYBOOKG3(USBMS):
|
|||||||
newpath = os.path.join(newpath, mdata.get('title', ''))
|
newpath = os.path.join(newpath, mdata.get('title', ''))
|
||||||
newpath = os.path.join(newpath, mdata.get('timestamp', ''))
|
newpath = os.path.join(newpath, mdata.get('timestamp', ''))
|
||||||
elif tag.startswith('/'):
|
elif tag.startswith('/'):
|
||||||
newpath = path
|
|
||||||
newpath += tag
|
newpath += tag
|
||||||
newpath = os.path.normpath(newpath)
|
newpath = os.path.normpath(newpath)
|
||||||
break
|
break
|
||||||
@ -125,10 +94,15 @@ class CYBOOKG3(USBMS):
|
|||||||
t2b.write_t2b(t2bfile, coverdata)
|
t2b.write_t2b(t2bfile, coverdata)
|
||||||
t2bfile.close()
|
t2bfile.close()
|
||||||
|
|
||||||
|
self.report_progress(i / float(len(files)), _('Transferring books to device...'))
|
||||||
|
|
||||||
|
self.report_progress(1.0, _('Transferring books to device...'))
|
||||||
|
|
||||||
return zip(paths, cycle([on_card]))
|
return zip(paths, cycle([on_card]))
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
def delete_books(self, paths, end_session=True):
|
||||||
for path in paths:
|
for i, path in enumerate(paths):
|
||||||
|
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
|
|
||||||
@ -148,4 +122,4 @@ class CYBOOKG3(USBMS):
|
|||||||
os.removedirs(os.path.dirname(path))
|
os.removedirs(os.path.dirname(path))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
self.report_progress(1.0, _('Removing books from device...'))
|
||||||
|
@ -52,27 +52,34 @@ class JETBOOK(USBMS):
|
|||||||
names = iter(names)
|
names = iter(names)
|
||||||
metadata = iter(metadata)
|
metadata = iter(metadata)
|
||||||
|
|
||||||
for infile in files:
|
for i, infile in enumerate(files):
|
||||||
newpath = path
|
newpath = path
|
||||||
|
|
||||||
if self.SUPPORTS_SUB_DIRS:
|
|
||||||
mdata = metadata.next()
|
mdata = metadata.next()
|
||||||
|
|
||||||
if 'tags' in mdata.keys():
|
if 'tags' in mdata.keys():
|
||||||
for tag in mdata['tags']:
|
for tag in mdata['tags']:
|
||||||
if tag.startswith('/'):
|
if tag.startswith(_('News')):
|
||||||
|
newpath = os.path.join(newpath, 'news')
|
||||||
|
newpath = os.path.join(newpath, mdata.get('title', ''))
|
||||||
|
newpath = os.path.join(newpath, mdata.get('timestamp', ''))
|
||||||
|
break
|
||||||
|
elif tag.startswith('/'):
|
||||||
newpath += tag
|
newpath += tag
|
||||||
newpath = os.path.normpath(newpath)
|
newpath = os.path.normpath(newpath)
|
||||||
break
|
break
|
||||||
|
|
||||||
if not os.path.exists(newpath):
|
|
||||||
os.makedirs(newpath)
|
|
||||||
|
|
||||||
author = sanitize(mdata.get('authors','Unknown')).replace(' ', '_')
|
author = sanitize(mdata.get('authors','Unknown')).replace(' ', '_')
|
||||||
title = sanitize(mdata.get('title', 'Unknown')).replace(' ', '_')
|
title = sanitize(mdata.get('title', 'Unknown')).replace(' ', '_')
|
||||||
fileext = os.path.splitext(os.path.basename(names.next()))[1]
|
fileext = os.path.splitext(os.path.basename(names.next()))[1]
|
||||||
fname = '%s#%s%s' % (author, title, fileext)
|
fname = '%s#%s%s' % (author, title, fileext)
|
||||||
|
|
||||||
|
if newpath == path:
|
||||||
|
newpath = os.path.join(newpath, author, title)
|
||||||
|
|
||||||
|
if not os.path.exists(newpath):
|
||||||
|
os.makedirs(newpath)
|
||||||
|
|
||||||
filepath = os.path.join(newpath, fname)
|
filepath = os.path.join(newpath, fname)
|
||||||
paths.append(filepath)
|
paths.append(filepath)
|
||||||
|
|
||||||
@ -87,6 +94,10 @@ class JETBOOK(USBMS):
|
|||||||
else:
|
else:
|
||||||
shutil.copy2(infile, filepath)
|
shutil.copy2(infile, filepath)
|
||||||
|
|
||||||
|
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
|
||||||
|
|
||||||
|
self.report_progress(1.0, _('Transferring books to device...'))
|
||||||
|
|
||||||
return zip(paths, cycle([on_card]))
|
return zip(paths, cycle([on_card]))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -39,7 +39,8 @@ class KINDLE(USBMS):
|
|||||||
r'(?P<title>[^-]+)-asin_(?P<asin>[a-zA-Z\d]{10,})-type_(?P<type>\w{4})-v_(?P<index>\d+).*')
|
r'(?P<title>[^-]+)-asin_(?P<asin>[a-zA-Z\d]{10,})-type_(?P<type>\w{4})-v_(?P<index>\d+).*')
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
def delete_books(self, paths, end_session=True):
|
||||||
for path in paths:
|
for i, path in enumerate(paths):
|
||||||
|
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
|
|
||||||
@ -48,6 +49,7 @@ class KINDLE(USBMS):
|
|||||||
# Delete the ebook auxiliary file
|
# Delete the ebook auxiliary file
|
||||||
if os.path.exists(filepath + '.mbp'):
|
if os.path.exists(filepath + '.mbp'):
|
||||||
os.unlink(filepath + '.mbp')
|
os.unlink(filepath + '.mbp')
|
||||||
|
self.report_progress(1.0, _('Removing books from device...'))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def metadata_from_path(cls, path):
|
def metadata_from_path(cls, path):
|
||||||
|
@ -129,7 +129,7 @@ class Book(object):
|
|||||||
|
|
||||||
class BookList(_BookList):
|
class BookList(_BookList):
|
||||||
|
|
||||||
def __init__(self, xml_file, mountpath):
|
def __init__(self, xml_file, mountpath, report_progress=None):
|
||||||
_BookList.__init__(self)
|
_BookList.__init__(self)
|
||||||
xml_file.seek(0)
|
xml_file.seek(0)
|
||||||
self.document = dom.parse(xml_file)
|
self.document = dom.parse(xml_file)
|
||||||
@ -144,7 +144,10 @@ class BookList(_BookList):
|
|||||||
else:
|
else:
|
||||||
self.prefix = ''
|
self.prefix = ''
|
||||||
|
|
||||||
for book in self.root_element.childNodes:
|
nodes = self.root_element.childNodes
|
||||||
|
for i, book in enumerate(nodes):
|
||||||
|
if report_progress:
|
||||||
|
self.report_progress((i+1) / float(len(nodes)), _('Getting list of books on device...'))
|
||||||
if hasattr(book, 'tagName') and book.tagName.endswith('text'):
|
if hasattr(book, 'tagName') and book.tagName.endswith('text'):
|
||||||
tags = [i.getAttribute('title') for i in self.get_playlists(book.getAttribute('id'))]
|
tags = [i.getAttribute('title') for i in self.get_playlists(book.getAttribute('id'))]
|
||||||
self.append(Book(book, mountpath, tags, prefix=self.prefix))
|
self.append(Book(book, mountpath, tags, prefix=self.prefix))
|
||||||
|
@ -75,24 +75,29 @@ class PRS505(CLI, Device):
|
|||||||
self._card_b_prefix = None
|
self._card_b_prefix = None
|
||||||
|
|
||||||
def get_device_information(self, end_session=True):
|
def get_device_information(self, end_session=True):
|
||||||
|
self.report_progress(1.0, _('Get device information...'))
|
||||||
return (self.__class__.__name__, '', '', '')
|
return (self.__class__.__name__, '', '', '')
|
||||||
|
|
||||||
def books(self, oncard=None, end_session=True):
|
def books(self, oncard=None, end_session=True):
|
||||||
if oncard == 'carda' and not self._card_a_prefix:
|
if oncard == 'carda' and not self._card_a_prefix:
|
||||||
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
return []
|
return []
|
||||||
elif oncard == 'cardb' and not self._card_b_prefix:
|
elif oncard == 'cardb' and not self._card_b_prefix:
|
||||||
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
return []
|
return []
|
||||||
elif oncard and oncard != 'carda' and oncard != 'cardb':
|
elif oncard and oncard != 'carda' and oncard != 'cardb':
|
||||||
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
return []
|
return []
|
||||||
|
|
||||||
db = self.__class__.CACHE_XML if oncard else self.__class__.MEDIA_XML
|
db = self.__class__.CACHE_XML if oncard else self.__class__.MEDIA_XML
|
||||||
prefix = self._card_a_prefix if oncard == 'carda' else self._card_b_prefix if oncard == 'cardb' else self._main_prefix
|
prefix = self._card_a_prefix if oncard == 'carda' else self._card_b_prefix if oncard == 'cardb' else self._main_prefix
|
||||||
bl = BookList(open(prefix + db, 'rb'), prefix)
|
bl = BookList(open(prefix + db, 'rb'), prefix, self.report_progress)
|
||||||
paths = bl.purge_corrupted_files()
|
paths = bl.purge_corrupted_files()
|
||||||
for path in paths:
|
for path in paths:
|
||||||
path = os.path.join(prefix, path)
|
path = os.path.join(prefix, path)
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
return bl
|
return bl
|
||||||
|
|
||||||
def upload_books(self, files, names, on_card=None, end_session=True,
|
def upload_books(self, files, names, on_card=None, end_session=True,
|
||||||
@ -133,7 +138,7 @@ class PRS505(CLI, Device):
|
|||||||
|
|
||||||
names = iter(names)
|
names = iter(names)
|
||||||
metadata = iter(metadata)
|
metadata = iter(metadata)
|
||||||
for infile in files:
|
for i, infile in enumerate(files):
|
||||||
close = False
|
close = False
|
||||||
if not hasattr(infile, 'read'):
|
if not hasattr(infile, 'read'):
|
||||||
infile, close = open(infile, 'rb'), True
|
infile, close = open(infile, 'rb'), True
|
||||||
@ -170,6 +175,10 @@ class PRS505(CLI, Device):
|
|||||||
infile.close()
|
infile.close()
|
||||||
ctimes.append(os.path.getctime(paths[-1]))
|
ctimes.append(os.path.getctime(paths[-1]))
|
||||||
|
|
||||||
|
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
|
||||||
|
|
||||||
|
self.report_progress(1.0, _('Transferring books to device...'))
|
||||||
|
|
||||||
return zip(paths, sizes, ctimes, cycle([on_card]))
|
return zip(paths, sizes, ctimes, cycle([on_card]))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -186,9 +195,11 @@ class PRS505(CLI, Device):
|
|||||||
fix_ids(*booklists)
|
fix_ids(*booklists)
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
def delete_books(self, paths, end_session=True):
|
||||||
for path in paths:
|
for i, path in enumerate(paths):
|
||||||
|
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
|
self.report_progress(1.0, _('Removing books from device...'))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remove_books_from_metadata(cls, paths, booklists):
|
def remove_books_from_metadata(cls, paths, booklists):
|
||||||
@ -215,3 +226,5 @@ class PRS505(CLI, Device):
|
|||||||
f.close()
|
f.close()
|
||||||
write_card_prefix(self._card_a_prefix, 1)
|
write_card_prefix(self._card_a_prefix, 1)
|
||||||
write_card_prefix(self._card_b_prefix, 2)
|
write_card_prefix(self._card_b_prefix, 2)
|
||||||
|
|
||||||
|
self.report_progress(1.0, _('Sending metadata to device...'))
|
||||||
|
@ -38,6 +38,7 @@ class USBMS(CLI, Device):
|
|||||||
report_progress=report_progress)
|
report_progress=report_progress)
|
||||||
|
|
||||||
def get_device_information(self, end_session=True):
|
def get_device_information(self, end_session=True):
|
||||||
|
self.report_progress(1.0, _('Get device information...'))
|
||||||
return (self.__class__.__name__, '', '', '')
|
return (self.__class__.__name__, '', '', '')
|
||||||
|
|
||||||
def books(self, oncard=None, end_session=True):
|
def books(self, oncard=None, end_session=True):
|
||||||
@ -45,10 +46,13 @@ class USBMS(CLI, Device):
|
|||||||
bl = BookList()
|
bl = BookList()
|
||||||
|
|
||||||
if oncard == 'carda' and not self._card_a_prefix:
|
if oncard == 'carda' and not self._card_a_prefix:
|
||||||
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
return bl
|
return bl
|
||||||
elif oncard == 'cardb' and not self._card_b_prefix:
|
elif oncard == 'cardb' and not self._card_b_prefix:
|
||||||
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
return bl
|
return bl
|
||||||
elif oncard and oncard != 'carda' and oncard != 'cardb':
|
elif oncard and oncard != 'carda' and oncard != 'cardb':
|
||||||
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
return bl
|
return bl
|
||||||
|
|
||||||
prefix = self._card_a_prefix if oncard == 'carda' else self._card_b_prefix if oncard == 'cardb' else self._main_prefix
|
prefix = self._card_a_prefix if oncard == 'carda' else self._card_b_prefix if oncard == 'cardb' else self._main_prefix
|
||||||
@ -59,13 +63,20 @@ class USBMS(CLI, Device):
|
|||||||
for path, dirs, files in os.walk(os.path.join(prefix, ebook_dir)):
|
for path, dirs, files in os.walk(os.path.join(prefix, ebook_dir)):
|
||||||
# Filter out anything that isn't in the list of supported ebook types
|
# Filter out anything that isn't in the list of supported ebook types
|
||||||
for book_type in self.FORMATS:
|
for book_type in self.FORMATS:
|
||||||
for filename in fnmatch.filter(files, '*.%s' % (book_type)):
|
match = fnmatch.filter(files, '*.%s' % (book_type))
|
||||||
|
for i, filename in enumerate(match):
|
||||||
|
self.report_progress((i+1) / float(len(match)), _('Getting list of books on device...'))
|
||||||
bl.append(self.__class__.book_from_path(os.path.join(path, filename)))
|
bl.append(self.__class__.book_from_path(os.path.join(path, filename)))
|
||||||
else:
|
else:
|
||||||
path = os.path.join(prefix, ebook_dir)
|
path = os.path.join(prefix, ebook_dir)
|
||||||
for filename in os.listdir(path):
|
paths = os.listdir(path)
|
||||||
|
for i, filename in enumerate(paths):
|
||||||
|
self.report_progress((i+1) / float(len(paths)), _('Getting list of books on device...'))
|
||||||
if path_to_ext(filename) in self.FORMATS:
|
if path_to_ext(filename) in self.FORMATS:
|
||||||
bl.append(self.__class__.book_from_path(os.path.join(path, filename)))
|
bl.append(self.__class__.book_from_path(os.path.join(path, filename)))
|
||||||
|
|
||||||
|
self.report_progress(1.0, _('Getting list of books on device...'))
|
||||||
|
|
||||||
return bl
|
return bl
|
||||||
|
|
||||||
def _sanity_check(self, on_card, files):
|
def _sanity_check(self, on_card, files):
|
||||||
@ -78,7 +89,7 @@ class USBMS(CLI, Device):
|
|||||||
|
|
||||||
if on_card == 'carda':
|
if on_card == 'carda':
|
||||||
path = os.path.join(self._card_a_prefix, self.EBOOK_DIR_CARD_A)
|
path = os.path.join(self._card_a_prefix, self.EBOOK_DIR_CARD_A)
|
||||||
if on_card == 'cardb':
|
elif on_card == 'cardb':
|
||||||
path = os.path.join(self._card_b_prefix, self.EBOOK_DIR_CARD_B)
|
path = os.path.join(self._card_b_prefix, self.EBOOK_DIR_CARD_B)
|
||||||
else:
|
else:
|
||||||
path = os.path.join(self._main_prefix, self.EBOOK_DIR_MAIN)
|
path = os.path.join(self._main_prefix, self.EBOOK_DIR_MAIN)
|
||||||
@ -102,7 +113,7 @@ class USBMS(CLI, Device):
|
|||||||
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
|
raise FreeSpaceError(_("There is insufficient free space on the storage card"))
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def upload_books(self, files, names, on_card=False, end_session=True,
|
def upload_books(self, files, names, on_card=None, end_session=True,
|
||||||
metadata=None):
|
metadata=None):
|
||||||
|
|
||||||
path = self._sanity_check(on_card, files)
|
path = self._sanity_check(on_card, files)
|
||||||
@ -111,7 +122,7 @@ class USBMS(CLI, Device):
|
|||||||
names = iter(names)
|
names = iter(names)
|
||||||
metadata = iter(metadata)
|
metadata = iter(metadata)
|
||||||
|
|
||||||
for infile in files:
|
for i, infile in enumerate(files):
|
||||||
newpath = path
|
newpath = path
|
||||||
|
|
||||||
if self.SUPPORTS_SUB_DIRS:
|
if self.SUPPORTS_SUB_DIRS:
|
||||||
@ -125,14 +136,14 @@ class USBMS(CLI, Device):
|
|||||||
newpath = os.path.join(newpath, mdata.get('timestamp', ''))
|
newpath = os.path.join(newpath, mdata.get('timestamp', ''))
|
||||||
break
|
break
|
||||||
elif tag.startswith('/'):
|
elif tag.startswith('/'):
|
||||||
newpath = path
|
|
||||||
newpath += tag
|
newpath += tag
|
||||||
newpath = os.path.normpath(newpath)
|
newpath = os.path.normpath(newpath)
|
||||||
break
|
break
|
||||||
|
|
||||||
if newpath == path:
|
if newpath == path:
|
||||||
newpath = os.path.join(newpath, mdata.get('authors', _('Unknown')))
|
newpath = os.path.join(newpath,
|
||||||
newpath = os.path.join(newpath, mdata.get('title', _('Unknown')))
|
mdata.get('authors', _('Unknown')),
|
||||||
|
mdata.get('title', _('Unknown')))
|
||||||
|
|
||||||
if not os.path.exists(newpath):
|
if not os.path.exists(newpath):
|
||||||
os.makedirs(newpath)
|
os.makedirs(newpath)
|
||||||
@ -151,22 +162,28 @@ class USBMS(CLI, Device):
|
|||||||
else:
|
else:
|
||||||
shutil.copy2(infile, filepath)
|
shutil.copy2(infile, filepath)
|
||||||
|
|
||||||
|
self.report_progress((i+1) / float(len(files)), _('Transferring books to device...'))
|
||||||
|
|
||||||
|
self.report_progress(1.0, _('Transferring books to device...'))
|
||||||
|
|
||||||
return zip(paths, cycle([on_card]))
|
return zip(paths, cycle([on_card]))
|
||||||
|
|
||||||
@classmethod
|
def add_books_to_metadata(self, locations, metadata, booklists):
|
||||||
def add_books_to_metadata(cls, locations, metadata, booklists):
|
for i, location in enumerate(locations):
|
||||||
for location in locations:
|
self.report_progress((i+1) / float(len(locations)), _('Adding books to device metadata listing...'))
|
||||||
path = location[0]
|
path = location[0]
|
||||||
blist = 2 if location[1] == 'cardb' else 1 if location[1] == 'carda' else 0
|
blist = 2 if location[1] == 'cardb' else 1 if location[1] == 'carda' else 0
|
||||||
|
|
||||||
book = cls.book_from_path(path)
|
book = self.book_from_path(path)
|
||||||
|
|
||||||
if not book in booklists[blist]:
|
if not book in booklists[blist]:
|
||||||
booklists[blist].append(book)
|
booklists[blist].append(book)
|
||||||
|
self.report_progress(1.0, _('Adding books to device metadata listing...'))
|
||||||
|
|
||||||
|
|
||||||
def delete_books(self, paths, end_session=True):
|
def delete_books(self, paths, end_session=True):
|
||||||
for path in paths:
|
for i, path in enumerate(paths):
|
||||||
|
self.report_progress((i+1) / float(len(paths)), _('Removing books from device...'))
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
# Delete the ebook
|
# Delete the ebook
|
||||||
os.unlink(path)
|
os.unlink(path)
|
||||||
@ -175,20 +192,22 @@ class USBMS(CLI, Device):
|
|||||||
os.removedirs(os.path.dirname(path))
|
os.removedirs(os.path.dirname(path))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
self.report_progress(1.0, _('Removing books from device...'))
|
||||||
|
|
||||||
@classmethod
|
def remove_books_from_metadata(self, paths, booklists):
|
||||||
def remove_books_from_metadata(cls, paths, booklists):
|
for i, path in enumerate(paths):
|
||||||
for path in paths:
|
self.report_progress((i+1) / float(len(paths)), _('Removing books from device metadata listing...'))
|
||||||
for bl in booklists:
|
for bl in booklists:
|
||||||
for book in bl:
|
for book in bl:
|
||||||
if path.endswith(book.path):
|
if path.endswith(book.path):
|
||||||
bl.remove(book)
|
bl.remove(book)
|
||||||
|
self.report_progress(1.0, _('Removing books from device metadata listing...'))
|
||||||
|
|
||||||
def sync_booklists(self, booklists, end_session=True):
|
def sync_booklists(self, booklists, end_session=True):
|
||||||
# There is no meta data on the device to update. The device is treated
|
# There is no meta data on the device to update. The device is treated
|
||||||
# as a mass storage device and does not use a meta data xml file like
|
# as a mass storage device and does not use a meta data xml file like
|
||||||
# the Sony Readers.
|
# the Sony Readers.
|
||||||
pass
|
self.report_progress(1.0, _('Sending metadata to device...'))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def metadata_from_path(cls, path):
|
def metadata_from_path(cls, path):
|
||||||
|
@ -100,27 +100,31 @@ def available_width():
|
|||||||
def extension(path):
|
def extension(path):
|
||||||
return os.path.splitext(path)[1][1:].lower()
|
return os.path.splitext(path)[1][1:].lower()
|
||||||
|
|
||||||
def warning_dialog(parent, title, msg):
|
def warning_dialog(parent, title, msg, det_msg=''):
|
||||||
d = QMessageBox(QMessageBox.Warning, 'WARNING: '+title, msg, QMessageBox.Ok,
|
d = QMessageBox(QMessageBox.Warning, 'WARNING: '+title, msg, QMessageBox.Ok,
|
||||||
parent)
|
parent)
|
||||||
|
d.setDetailedText(det_msg)
|
||||||
d.setIconPixmap(QPixmap(':/images/dialog_warning.svg'))
|
d.setIconPixmap(QPixmap(':/images/dialog_warning.svg'))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def error_dialog(parent, title, msg):
|
def error_dialog(parent, title, msg, det_msg=''):
|
||||||
d = QMessageBox(QMessageBox.Critical, 'ERROR: '+title, msg, QMessageBox.Ok,
|
d = QMessageBox(QMessageBox.Critical, 'ERROR: '+title, msg, QMessageBox.Ok,
|
||||||
parent)
|
parent)
|
||||||
|
d.setDetailedText(det_msg)
|
||||||
d.setIconPixmap(QPixmap(':/images/dialog_error.svg'))
|
d.setIconPixmap(QPixmap(':/images/dialog_error.svg'))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def question_dialog(parent, title, msg):
|
def question_dialog(parent, title, msg, det_msg=''):
|
||||||
d = QMessageBox(QMessageBox.Question, title, msg, QMessageBox.Yes|QMessageBox.No,
|
d = QMessageBox(QMessageBox.Question, title, msg, QMessageBox.Yes|QMessageBox.No,
|
||||||
parent)
|
parent)
|
||||||
|
d.setDetailedText(det_msg)
|
||||||
d.setIconPixmap(QPixmap(':/images/dialog_information.svg'))
|
d.setIconPixmap(QPixmap(':/images/dialog_information.svg'))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def info_dialog(parent, title, msg):
|
def info_dialog(parent, title, msg, det_msg=''):
|
||||||
d = QMessageBox(QMessageBox.Information, title, msg, QMessageBox.NoButton,
|
d = QMessageBox(QMessageBox.Information, title, msg, QMessageBox.NoButton,
|
||||||
parent)
|
parent)
|
||||||
|
d.setDetailedText(det_msg)
|
||||||
d.setIconPixmap(QPixmap(':/images/dialog_information.svg'))
|
d.setIconPixmap(QPixmap(':/images/dialog_information.svg'))
|
||||||
return d
|
return d
|
||||||
|
|
||||||
|
@ -507,10 +507,10 @@ class DeviceGUI(object):
|
|||||||
self.status_bar.showMessage(_('Sending email to')+' '+to, 3000)
|
self.status_bar.showMessage(_('Sending email to')+' '+to, 3000)
|
||||||
|
|
||||||
if bad:
|
if bad:
|
||||||
bad = '\n'.join('<li>%s</li>'%(i,) for i in bad)
|
bad = '\n'.join('%s'%(i,) for i in bad)
|
||||||
d = warning_dialog(self, _('No suitable formats'),
|
d = warning_dialog(self, _('No suitable formats'),
|
||||||
'<p>'+ _('Could not email the following books '
|
_('Could not email the following books '
|
||||||
'as no suitable formats were found:<br><ul>%s</ul>')%(bad,))
|
'as no suitable formats were found:'), bad)
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def emails_sent(self, results, remove=[]):
|
def emails_sent(self, results, remove=[]):
|
||||||
@ -551,7 +551,7 @@ class DeviceGUI(object):
|
|||||||
for account, x in opts.accounts.items() if x[1]]
|
for account, x in opts.accounts.items() if x[1]]
|
||||||
sent_mails = []
|
sent_mails = []
|
||||||
for account, fmts in accounts:
|
for account, fmts in accounts:
|
||||||
files = self.library_view.model().\
|
files, auto = self.library_view.model().\
|
||||||
get_preferred_formats_from_ids([id], fmts)
|
get_preferred_formats_from_ids([id], fmts)
|
||||||
files = [f.name for f in files if f is not None]
|
files = [f.name for f in files if f is not None]
|
||||||
if not files:
|
if not files:
|
||||||
@ -580,7 +580,7 @@ class DeviceGUI(object):
|
|||||||
if self.device_connected:
|
if self.device_connected:
|
||||||
ids = list(dynamic.get('news_to_be_synced', set([])))
|
ids = list(dynamic.get('news_to_be_synced', set([])))
|
||||||
ids = [id for id in ids if self.library_view.model().db.has_id(id)]
|
ids = [id for id in ids if self.library_view.model().db.has_id(id)]
|
||||||
files = self.library_view.model().get_preferred_formats_from_ids(
|
files, auto = self.library_view.model().get_preferred_formats_from_ids(
|
||||||
ids, self.device_manager.device_class.settings().format_map)
|
ids, self.device_manager.device_class.settings().format_map)
|
||||||
files = [f for f in files if f is not None]
|
files = [f for f in files if f is not None]
|
||||||
if not files:
|
if not files:
|
||||||
@ -627,8 +627,8 @@ class DeviceGUI(object):
|
|||||||
else:
|
else:
|
||||||
_auto_ids = []
|
_auto_ids = []
|
||||||
|
|
||||||
ids = iter(ids)
|
|
||||||
metadata = self.library_view.model().get_metadata(ids, True)
|
metadata = self.library_view.model().get_metadata(ids, True)
|
||||||
|
ids = iter(ids)
|
||||||
for mi in metadata:
|
for mi in metadata:
|
||||||
cdata = mi['cover']
|
cdata = mi['cover']
|
||||||
if cdata:
|
if cdata:
|
||||||
@ -663,19 +663,19 @@ class DeviceGUI(object):
|
|||||||
|
|
||||||
auto = []
|
auto = []
|
||||||
if _auto_ids != []:
|
if _auto_ids != []:
|
||||||
for row in _auto_ids:
|
for id in _auto_ids:
|
||||||
if specific_format == None:
|
if specific_format == None:
|
||||||
formats = [f.lower() for f in self.library_view.model().db.formats(row).split(',')]
|
formats = [f.lower() for f in self.library_view.model().db.formats(id, index_is_id=True).split(',')]
|
||||||
formats = formats if formats != None else []
|
formats = formats if formats != None else []
|
||||||
if list(set(formats).intersection(available_input_formats())) != [] and list(set(self.device_manager.device_class.settings().format_map).intersection(available_output_formats())) != []:
|
if list(set(formats).intersection(available_input_formats())) != [] and list(set(self.device_manager.device_class.settings().format_map).intersection(available_output_formats())) != []:
|
||||||
auto.append(row)
|
auto.append(id)
|
||||||
else:
|
else:
|
||||||
bad.append(self.library_view.model().title(row))
|
bad.append(self.library_view.model().db.title(id, index_is_id=True))
|
||||||
else:
|
else:
|
||||||
if specific_format in available_output_formats():
|
if specific_format in available_output_formats():
|
||||||
auto.append(row)
|
auto.append(id)
|
||||||
else:
|
else:
|
||||||
bad.append(self.library_view.model().title(row))
|
bad.append(self.library_view.model().db.title(id, index_is_id=True))
|
||||||
|
|
||||||
if auto != []:
|
if auto != []:
|
||||||
format = None
|
format = None
|
||||||
@ -686,7 +686,7 @@ class DeviceGUI(object):
|
|||||||
if format is None:
|
if format is None:
|
||||||
bad += auto
|
bad += auto
|
||||||
else:
|
else:
|
||||||
autos = [self.library_view.model().title(row) for row in auto]
|
autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto]
|
||||||
autos = '\n'.join('<li>%s</li>'%(i,) for i in autos)
|
autos = '\n'.join('<li>%s</li>'%(i,) for i in autos)
|
||||||
d = info_dialog(self, _('No suitable formats'),
|
d = info_dialog(self, _('No suitable formats'),
|
||||||
_('Auto converting the following books before uploading to the device:<br><ul>%s</ul>')%(autos,))
|
_('Auto converting the following books before uploading to the device:<br><ul>%s</ul>')%(autos,))
|
||||||
@ -694,12 +694,12 @@ class DeviceGUI(object):
|
|||||||
self.auto_convert(_auto_ids, on_card, format)
|
self.auto_convert(_auto_ids, on_card, format)
|
||||||
|
|
||||||
if bad:
|
if bad:
|
||||||
bad = '\n'.join('<li>%s</li>'%(i,) for i in bad)
|
bad = '\n'.join('%s'%(i,) for i in bad)
|
||||||
d = warning_dialog(self, _('No suitable formats'),
|
d = warning_dialog(self, _('No suitable formats'),
|
||||||
_('Could not upload the following books to the device, '
|
_('Could not upload the following books to the device, '
|
||||||
'as no suitable formats were found. Try changing the output '
|
'as no suitable formats were found. Try changing the output '
|
||||||
'format in the upper right corner next to the red heart and '
|
'format in the upper right corner next to the red heart and '
|
||||||
're-converting. <br><ul>%s</ul>')%(bad,))
|
're-converting.'), bad)
|
||||||
d.exec_()
|
d.exec_()
|
||||||
|
|
||||||
def upload_booklists(self):
|
def upload_booklists(self):
|
||||||
|
@ -397,27 +397,39 @@ class BooksModel(QAbstractTableModel):
|
|||||||
else:
|
else:
|
||||||
return metadata
|
return metadata
|
||||||
|
|
||||||
def get_preferred_formats_from_ids(self, ids, all_formats, mode='r+b'):
|
def get_preferred_formats_from_ids(self, ids, formats, paths=False,
|
||||||
|
set_metadata=False, specific_format=None,
|
||||||
|
exclude_auto=False, mode='r+b'):
|
||||||
ans = []
|
ans = []
|
||||||
|
need_auto = []
|
||||||
|
if specific_format is not None:
|
||||||
|
formats = [specific_format.lower()]
|
||||||
for id in ids:
|
for id in ids:
|
||||||
format = None
|
format = None
|
||||||
fmts = self.db.formats(id, index_is_id=True)
|
fmts = self.db.formats(id, index_is_id=True)
|
||||||
if not fmts:
|
if not fmts:
|
||||||
fmts = ''
|
fmts = ''
|
||||||
available_formats = set(fmts.lower().split(','))
|
db_formats = set(fmts.lower().split(','))
|
||||||
for f in all_formats:
|
available_formats = set([f.lower() for f in formats])
|
||||||
if f.lower() in available_formats:
|
u = available_formats.intersection(db_formats)
|
||||||
format = f.lower()
|
for f in formats:
|
||||||
|
if f.lower() in u:
|
||||||
|
format = f
|
||||||
break
|
break
|
||||||
if format is None:
|
if format is not None:
|
||||||
ans.append(format)
|
pt = PersistentTemporaryFile(suffix='.'+format)
|
||||||
|
pt.write(self.db.format(id, format, index_is_id=True))
|
||||||
|
pt.flush()
|
||||||
|
if set_metadata:
|
||||||
|
_set_metadata(pt, self.db.get_metadata(id, get_cover=True, index_is_id=True),
|
||||||
|
format)
|
||||||
|
pt.close() if paths else pt.seek(0)
|
||||||
|
ans.append(pt)
|
||||||
else:
|
else:
|
||||||
f = self.db.format(id, format, index_is_id=True, as_file=True,
|
need_auto.append(id)
|
||||||
mode=mode)
|
if not exclude_auto:
|
||||||
ans.append(f)
|
ans.append(None)
|
||||||
return ans
|
return ans, need_auto
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_preferred_formats(self, rows, formats, paths=False,
|
def get_preferred_formats(self, rows, formats, paths=False,
|
||||||
set_metadata=False, specific_format=None,
|
set_metadata=False, specific_format=None,
|
||||||
|
@ -445,14 +445,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
def change_output_format(self, x):
|
def change_output_format(self, x):
|
||||||
of = unicode(x).strip()
|
of = unicode(x).strip()
|
||||||
if of != prefs['output_format']:
|
if of != prefs['output_format']:
|
||||||
if of not in ('LRF', 'EPUB', 'MOBI'):
|
|
||||||
warning_dialog(self, 'Warning',
|
|
||||||
('<p>%s support is still in beta. If you find bugs, '
|
|
||||||
'please report them by opening a <a href="http://cal'
|
|
||||||
'ibre.kovidgoyal.net">ticket</a>.')%of).exec_()
|
|
||||||
prefs.set('output_format', of)
|
prefs.set('output_format', of)
|
||||||
|
|
||||||
|
|
||||||
def test_server(self, *args):
|
def test_server(self, *args):
|
||||||
if self.content_server.exception is not None:
|
if self.content_server.exception is not None:
|
||||||
error_dialog(self, _('Failed to start content server'),
|
error_dialog(self, _('Failed to start content server'),
|
||||||
@ -916,14 +910,14 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
callback=callback,
|
callback=callback,
|
||||||
single_format=single_format)
|
single_format=single_format)
|
||||||
if failures and single_format is not None:
|
if failures and single_format is not None:
|
||||||
msg = _('<p>Could not save the following books to disk, '
|
msg = _('Could not save the following books to disk, '
|
||||||
'because the %s format is not available for them:<ul>')\
|
'because the %s format is not available for them')\
|
||||||
%single_format.upper()
|
%single_format.upper()
|
||||||
|
det_msg = ''
|
||||||
for f in failures:
|
for f in failures:
|
||||||
msg += '<li>%s</li>'%f[1]
|
det_msg += '%s\n'%f[1]
|
||||||
msg += '</ul>'
|
|
||||||
warning_dialog(self, _('Could not save some ebooks'),
|
warning_dialog(self, _('Could not save some ebooks'),
|
||||||
msg).exec_()
|
msg, det_msg).exec_()
|
||||||
QDesktopServices.openUrl(QUrl('file:'+dir))
|
QDesktopServices.openUrl(QUrl('file:'+dir))
|
||||||
else:
|
else:
|
||||||
paths = self.current_view().model().paths(rows)
|
paths = self.current_view().model().paths(rows)
|
||||||
@ -972,7 +966,8 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
|
|||||||
|
|
||||||
def auto_convert(self, row_ids, on_card, format):
|
def auto_convert(self, row_ids, on_card, format):
|
||||||
previous = self.library_view.currentIndex()
|
previous = self.library_view.currentIndex()
|
||||||
|
rows = [x.row() for x in \
|
||||||
|
self.library_view.selectionModel().selectedRows()]
|
||||||
jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, row_ids, True, format)
|
jobs, changed, bad = convert_single_ebook(self, self.library_view.model().db, row_ids, True, format)
|
||||||
if jobs == []: return
|
if jobs == []: return
|
||||||
for func, args, desc, fmt, id, temp_files in jobs:
|
for func, args, desc, fmt, id, temp_files in jobs:
|
||||||
|
@ -12,6 +12,7 @@ import cPickle, os
|
|||||||
from PyQt4.Qt import QDialog
|
from PyQt4.Qt import QDialog
|
||||||
|
|
||||||
from calibre.ptempfile import PersistentTemporaryFile
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
|
from calibre.gui2 import warning_dialog
|
||||||
from calibre.gui2.convert import load_specifics
|
from calibre.gui2.convert import load_specifics
|
||||||
from calibre.gui2.convert.single import NoSupportedInputFormats
|
from calibre.gui2.convert.single import NoSupportedInputFormats
|
||||||
from calibre.gui2.convert.single import Config as SingleConfig
|
from calibre.gui2.convert.single import Config as SingleConfig
|
||||||
@ -33,6 +34,7 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, out_format
|
|||||||
d = SingleConfig(parent, db, book_id, None, out_format)
|
d = SingleConfig(parent, db, book_id, None, out_format)
|
||||||
|
|
||||||
if auto_conversion:
|
if auto_conversion:
|
||||||
|
d.accept()
|
||||||
result = QDialog.Accepted
|
result = QDialog.Accepted
|
||||||
else:
|
else:
|
||||||
result = d.exec_()
|
result = d.exec_()
|
||||||
@ -60,10 +62,12 @@ def convert_single_ebook(parent, db, book_ids, auto_conversion=False, out_format
|
|||||||
res = []
|
res = []
|
||||||
for id in bad:
|
for id in bad:
|
||||||
title = db.title(id, True)
|
title = db.title(id, True)
|
||||||
res.append('<li>%s</li>'%title)
|
res.append('%s'%title)
|
||||||
|
|
||||||
msg = _('<p>Could not convert %d of %d books, because no suitable source format was found.<ul>%s</ul>')%(len(res), total, '\n'.join(res))
|
msg = '%s' % '\n'.join(res)
|
||||||
warning_dialog(parent, _('Could not convert some books'), msg).exec_()
|
warning_dialog(parent, _('Could not convert some books'),
|
||||||
|
_('Could not convert %d of %d books, because no suitable source format was found.' % (len(res), total)),
|
||||||
|
msg).exec_()
|
||||||
|
|
||||||
return jobs, changed, bad
|
return jobs, changed, bad
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user