mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Also pass path to original files to device drivers when uploading so that device drivers that need to can usethe originals instead of the tem files with updated metadata
This commit is contained in:
parent
142d6a532e
commit
2fcba45013
@ -16,7 +16,7 @@ class NYTimes(BasicNewsRecipe):
|
||||
|
||||
title = 'New York Times Top Stories'
|
||||
__author__ = 'GRiker'
|
||||
language = _('English')
|
||||
language = 'en'
|
||||
description = 'Top Stories from the New York Times'
|
||||
|
||||
# List of sections typically included in Top Stories. Use a keyword from the
|
||||
|
@ -14,7 +14,6 @@ from calibre.devices.interface import DevicePlugin
|
||||
from calibre.ebooks.BeautifulSoup import BeautifulSoup
|
||||
from calibre.ebooks.metadata import MetaInformation
|
||||
from calibre.library.server.utils import strftime
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.utils.config import Config, config_dir
|
||||
from calibre.utils.date import parse_date
|
||||
from calibre.utils.logging import Log
|
||||
@ -775,10 +774,12 @@ class ITUNES(DevicePlugin):
|
||||
self._remove_from_iTunes(self.cached_books[path])
|
||||
|
||||
# Add to iTunes Library|Books
|
||||
if isinstance(file,PersistentTemporaryFile):
|
||||
added = self.iTunes.add(appscript.mactypes.File(file._name))
|
||||
else:
|
||||
added = self.iTunes.add(appscript.mactypes.File(file))
|
||||
fpath = file
|
||||
if getattr(file, 'orig_file_path', None) is not None:
|
||||
fpath = file.orig_file_path
|
||||
elif getattr(file, 'name', None) is not None:
|
||||
fpath = file.name
|
||||
added = self.iTunes.add(appscript.mactypes.File(fpath))
|
||||
|
||||
thumb = None
|
||||
if metadata[i].cover:
|
||||
@ -815,7 +816,7 @@ class ITUNES(DevicePlugin):
|
||||
this_book.device_collections = []
|
||||
this_book.library_id = added
|
||||
this_book.path = path
|
||||
this_book.size = self._get_device_book_size(file, added.size())
|
||||
this_book.size = self._get_device_book_size(fpath, added.size())
|
||||
this_book.thumbnail = thumb
|
||||
this_book.iTunes_id = added
|
||||
|
||||
@ -922,12 +923,15 @@ class ITUNES(DevicePlugin):
|
||||
self.log.info(" '%s' not in cached_books" % metadata[i].title)
|
||||
|
||||
# Add to iTunes Library|Books
|
||||
if isinstance(file,PersistentTemporaryFile):
|
||||
op_status = lib_books.AddFile(file._name)
|
||||
self.log.info("ITUNES.upload_books():\n iTunes adding '%s'" % file._name)
|
||||
else:
|
||||
op_status = lib_books.AddFile(file)
|
||||
self.log.info(" iTunes adding '%s'" % file)
|
||||
fpath = file
|
||||
if getattr(file, 'orig_file_path', None) is not None:
|
||||
fpath = file.orig_file_path
|
||||
elif getattr(file, 'name', None) is not None:
|
||||
fpath = file.name
|
||||
|
||||
op_status = lib_books.AddFile(fpath)
|
||||
self.log.info("ITUNES.upload_books():\n iTunes adding '%s'"
|
||||
% fpath)
|
||||
|
||||
if DEBUG:
|
||||
sys.stdout.write(" iTunes copying '%s' ..." % metadata[i].title)
|
||||
@ -1464,7 +1468,7 @@ class ITUNES(DevicePlugin):
|
||||
# Read the current storage path for iTunes media
|
||||
cmd = "defaults read com.apple.itunes NSNavLastRootDirectory"
|
||||
proc = subprocess.Popen( cmd, shell=True, cwd=os.curdir, stdout=subprocess.PIPE)
|
||||
retcode = proc.wait()
|
||||
proc.wait()
|
||||
media_dir = os.path.abspath(proc.communicate()[0].strip())
|
||||
if os.path.exists(media_dir):
|
||||
self.iTunes_media = media_dir
|
||||
|
@ -287,7 +287,9 @@ class DevicePlugin(Plugin):
|
||||
This method should raise a L{FreeSpaceError} if there is not enough
|
||||
free space on the device. The text of the FreeSpaceError must contain the
|
||||
word "card" if C{on_card} is not None otherwise it must contain the word "memory".
|
||||
:files: A list of paths and/or file-like objects.
|
||||
:files: A list of paths and/or file-like objects. If they are paths and
|
||||
the paths point to temporary files, they may have an additional
|
||||
attribute, original_file_path pointing to the originals.
|
||||
:names: A list of file names that the books should have
|
||||
once uploaded to the device. len(names) == len(files)
|
||||
:return: A list of 3-element tuples. The list is meant to be passed
|
||||
|
@ -108,7 +108,7 @@ class BookList(_BookList):
|
||||
def add_book(self, book, replace_metadata):
|
||||
try:
|
||||
b = self.index(book)
|
||||
except ValueError, IndexError:
|
||||
except (ValueError, IndexError):
|
||||
b = None
|
||||
if b is None:
|
||||
self.append(book)
|
||||
|
@ -765,12 +765,8 @@ class Device(DeviceConfig, DevicePlugin):
|
||||
path = existing[0]
|
||||
|
||||
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)
|
||||
path = getattr(obj, 'name', obj)
|
||||
return os.path.getsize(path)
|
||||
|
||||
sizes = [get_size(f) for f in files]
|
||||
size = sum(sizes)
|
||||
|
@ -1,6 +1,8 @@
|
||||
from __future__ import with_statement
|
||||
__license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
|
||||
# Imports {{{
|
||||
import os, traceback, Queue, time, socket, cStringIO, re
|
||||
from threading import Thread, RLock
|
||||
from itertools import repeat
|
||||
@ -27,7 +29,9 @@ from calibre.utils.smtp import compose_mail, sendmail, extract_email_address, \
|
||||
config as email_config
|
||||
from calibre.devices.folder_device.driver import FOLDER_DEVICE
|
||||
|
||||
class DeviceJob(BaseJob):
|
||||
# }}}
|
||||
|
||||
class DeviceJob(BaseJob): # {{{
|
||||
|
||||
def __init__(self, func, done, job_manager, args=[], kwargs={},
|
||||
description=''):
|
||||
@ -78,8 +82,9 @@ class DeviceJob(BaseJob):
|
||||
def log_file(self):
|
||||
return cStringIO.StringIO(self._details.encode('utf-8'))
|
||||
|
||||
# }}}
|
||||
|
||||
class DeviceManager(Thread):
|
||||
class DeviceManager(Thread): # {{{
|
||||
|
||||
def __init__(self, connected_slot, job_manager, open_feedback_slot, sleep_time=2):
|
||||
'''
|
||||
@ -338,8 +343,9 @@ class DeviceManager(Thread):
|
||||
return self.create_job(self._view_book, done, args=[path, target],
|
||||
description=_('View book on device'))
|
||||
|
||||
# }}}
|
||||
|
||||
class DeviceAction(QAction):
|
||||
class DeviceAction(QAction): # {{{
|
||||
|
||||
a_s = pyqtSignal(object)
|
||||
|
||||
@ -356,9 +362,9 @@ class DeviceAction(QAction):
|
||||
def __repr__(self):
|
||||
return self.__class__.__name__ + ':%s:%s:%s'%(self.dest, self.delete,
|
||||
self.specific)
|
||||
# }}}
|
||||
|
||||
|
||||
class DeviceMenu(QMenu):
|
||||
class DeviceMenu(QMenu): # {{{
|
||||
|
||||
fetch_annotations = pyqtSignal()
|
||||
connect_to_folder = pyqtSignal()
|
||||
@ -532,8 +538,9 @@ class DeviceMenu(QMenu):
|
||||
annot_enable = enable and getattr(device, 'SUPPORTS_ANNOTATIONS', False)
|
||||
self.annotation_action.setEnabled(annot_enable)
|
||||
|
||||
# }}}
|
||||
|
||||
class Emailer(Thread):
|
||||
class Emailer(Thread): # {{{
|
||||
|
||||
def __init__(self, timeout=60):
|
||||
Thread.__init__(self)
|
||||
@ -590,6 +597,7 @@ class Emailer(Thread):
|
||||
results.append([jobname, e, traceback.format_exc()])
|
||||
callback(results)
|
||||
|
||||
# }}}
|
||||
|
||||
class DeviceGUI(object):
|
||||
|
||||
@ -637,7 +645,7 @@ class DeviceGUI(object):
|
||||
if not ids or len(ids) == 0:
|
||||
return
|
||||
files, _auto_ids = self.library_view.model().get_preferred_formats_from_ids(ids,
|
||||
fmts, paths=True, set_metadata=True,
|
||||
fmts, set_metadata=True,
|
||||
specific_format=specific_format,
|
||||
exclude_auto=do_auto_convert)
|
||||
if do_auto_convert:
|
||||
@ -647,7 +655,6 @@ class DeviceGUI(object):
|
||||
_auto_ids = []
|
||||
|
||||
full_metadata = self.library_view.model().metadata_for(ids)
|
||||
files = [getattr(f, 'name', None) for f in files]
|
||||
|
||||
bad, remove_ids, jobnames = [], [], []
|
||||
texts, subjects, attachments, attachment_names = [], [], [], []
|
||||
@ -760,7 +767,7 @@ class DeviceGUI(object):
|
||||
for account, fmts in accounts:
|
||||
files, auto = self.library_view.model().\
|
||||
get_preferred_formats_from_ids([id], fmts)
|
||||
files = [f.name for f in files if f is not None]
|
||||
files = [f for f in files if f is not None]
|
||||
if not files:
|
||||
continue
|
||||
attachment = files[0]
|
||||
@ -824,7 +831,7 @@ class DeviceGUI(object):
|
||||
prefix = prefix.decode(preferred_encoding, 'replace')
|
||||
prefix = ascii_filename(prefix)
|
||||
names.append('%s_%d%s'%(prefix, id,
|
||||
os.path.splitext(f.name)[1]))
|
||||
os.path.splitext(f)[1]))
|
||||
if mi.cover and os.access(mi.cover, os.R_OK):
|
||||
mi.thumbnail = self.cover_to_thumbnail(open(mi.cover,
|
||||
'rb').read())
|
||||
@ -837,7 +844,7 @@ class DeviceGUI(object):
|
||||
on_card = space.get(sorted(space.keys(), reverse=True)[0], None)
|
||||
self.upload_books(files, names, metadata,
|
||||
on_card=on_card,
|
||||
memory=[[f.name for f in files], remove])
|
||||
memory=[files, remove])
|
||||
self.status_bar.showMessage(_('Sending catalogs to device.'), 5000)
|
||||
|
||||
|
||||
@ -884,7 +891,7 @@ class DeviceGUI(object):
|
||||
prefix = prefix.decode(preferred_encoding, 'replace')
|
||||
prefix = ascii_filename(prefix)
|
||||
names.append('%s_%d%s'%(prefix, id,
|
||||
os.path.splitext(f.name)[1]))
|
||||
os.path.splitext(f)[1]))
|
||||
if mi.cover and os.access(mi.cover, os.R_OK):
|
||||
mi.thumbnail = self.cover_to_thumbnail(open(mi.cover,
|
||||
'rb').read())
|
||||
@ -898,7 +905,7 @@ class DeviceGUI(object):
|
||||
on_card = space.get(sorted(space.keys(), reverse=True)[0], None)
|
||||
self.upload_books(files, names, metadata,
|
||||
on_card=on_card,
|
||||
memory=[[f.name for f in files], remove])
|
||||
memory=[files, remove])
|
||||
self.status_bar.showMessage(_('Sending news to device.'), 5000)
|
||||
|
||||
|
||||
@ -914,7 +921,7 @@ class DeviceGUI(object):
|
||||
|
||||
_files, _auto_ids = self.library_view.model().get_preferred_formats_from_ids(ids,
|
||||
settings.format_map,
|
||||
paths=True, set_metadata=True,
|
||||
set_metadata=True,
|
||||
specific_format=specific_format,
|
||||
exclude_auto=do_auto_convert)
|
||||
if do_auto_convert:
|
||||
@ -930,9 +937,8 @@ class DeviceGUI(object):
|
||||
mi.thumbnail = self.cover_to_thumbnail(open(mi.cover, 'rb').read())
|
||||
imetadata = iter(metadata)
|
||||
|
||||
files = [getattr(f, 'name', None) for f in _files]
|
||||
bad, good, gf, names, remove_ids = [], [], [], [], []
|
||||
for f in files:
|
||||
for f in _files:
|
||||
mi = imetadata.next()
|
||||
id = ids.next()
|
||||
if f is None:
|
||||
|
@ -21,7 +21,8 @@ from calibre.utils.date import dt_factory, qt_to_dt, isoformat
|
||||
from calibre.ebooks.metadata.meta import set_metadata as _set_metadata
|
||||
from calibre.utils.search_query_parser import SearchQueryParser
|
||||
from calibre.library.caches import _match, CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH
|
||||
from calibre import strftime
|
||||
from calibre import strftime, isbytestring
|
||||
from calibre.constants import filesystem_encoding
|
||||
from calibre.gui2.library import DEFAULT_SORT
|
||||
|
||||
def human_readable(size, precision=1):
|
||||
@ -33,6 +34,13 @@ TIME_FMT = '%d %b %Y'
|
||||
ALIGNMENT_MAP = {'left': Qt.AlignLeft, 'right': Qt.AlignRight, 'center':
|
||||
Qt.AlignHCenter}
|
||||
|
||||
class FormatPath(unicode):
|
||||
|
||||
def __new__(cls, path, orig_file_path):
|
||||
ans = unicode.__new__(cls, path)
|
||||
ans.orig_file_path = orig_file_path
|
||||
return ans
|
||||
|
||||
class BooksModel(QAbstractTableModel): # {{{
|
||||
|
||||
about_to_be_sorted = pyqtSignal(object, name='aboutToBeSorted')
|
||||
@ -379,7 +387,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
else:
|
||||
return metadata
|
||||
|
||||
def get_preferred_formats_from_ids(self, ids, formats, paths=False,
|
||||
def get_preferred_formats_from_ids(self, ids, formats,
|
||||
set_metadata=False, specific_format=None,
|
||||
exclude_auto=False, mode='r+b'):
|
||||
ans = []
|
||||
@ -404,12 +412,20 @@ class BooksModel(QAbstractTableModel): # {{{
|
||||
as_file=True)) as src:
|
||||
shutil.copyfileobj(src, pt)
|
||||
pt.flush()
|
||||
if getattr(src, 'name', None):
|
||||
pt.orig_file_path = os.path.abspath(src.name)
|
||||
pt.seek(0)
|
||||
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)
|
||||
pt.close()
|
||||
def to_uni(x):
|
||||
if isbytestring(x):
|
||||
x = x.decode(filesystem_encoding)
|
||||
return x
|
||||
name, op = map(to_uni, map(os.path.abspath, (pt.name,
|
||||
pt.orig_file_path)))
|
||||
ans.append(FormatPath(name, op))
|
||||
else:
|
||||
need_auto.append(id)
|
||||
if not exclude_auto:
|
||||
|
Loading…
x
Reference in New Issue
Block a user