Pull from driver-dev

This commit is contained in:
Kovid Goyal 2009-05-16 15:49:42 -07:00
commit ecc05f20bc
7 changed files with 97 additions and 27 deletions

View File

@ -300,6 +300,17 @@ class PDFMetadataWriter(MetadataWriterPlugin):
from calibre.ebooks.metadata.pdf import set_metadata from calibre.ebooks.metadata.pdf import set_metadata
set_metadata(stream, mi) set_metadata(stream, mi)
class PDBMetadataWriter(MetadataWriterPlugin):
name = 'Set PDB metadata'
file_types = set(['pdb'])
description = _('Set metadata from %s files') % 'PDB'
author = 'John Schember'
def set_metadata(self, stream, mi, type):
from calibre.ebooks.metadata.pdb import set_metadata
set_metadata(stream, mi)
from calibre.ebooks.epub.input import EPUBInput from calibre.ebooks.epub.input import EPUBInput
from calibre.ebooks.mobi.input import MOBIInput from calibre.ebooks.mobi.input import MOBIInput

View File

@ -10,8 +10,8 @@ __docformat__ = 'restructuredtext en'
import re import re
from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import MetaInformation, authors_to_string
from calibre.ebooks.pdb.header import PdbHeaderReader from calibre.ebooks.pdb.header import PdbHeaderReader, PdbHeaderBuilder
from calibre.ebooks.pdb.ereader.reader import HeaderRecord from calibre.ebooks.pdb.ereader.reader import HeaderRecord
def get_metadata(stream, extract_cover=True): def get_metadata(stream, extract_cover=True):
@ -24,8 +24,8 @@ def get_metadata(stream, extract_cover=True):
pheader = PdbHeaderReader(stream) pheader = PdbHeaderReader(stream)
hr = HeaderRecord(pheader.section_data(0)) hr = HeaderRecord(pheader.section_data(0))
if hr.version in (2, 10): if hr.version in (2, 10) and hr.has_metadata == 1:
try: try:
mdata = pheader.section_data(hr.metadata_offset) mdata = pheader.section_data(hr.metadata_offset)
mdata = mdata.split('\x00') mdata = mdata.split('\x00')
@ -41,3 +41,42 @@ def get_metadata(stream, extract_cover=True):
return mi return mi
def set_metadata(stream, mi):
pheader = PdbHeaderReader(stream)
sections = [pheader.section_data(x) for x in range(0, pheader.section_count())]
hr = HeaderRecord(sections[0])
if hr.version not in (2, 10):
return
# Create a metadata record for the file if one does not alreay exist
if not hr.has_metadata:
sections += ['', 'MeTaInFo\x00']
last_data = len(sections) - 1
for i in range(0, 132, 2):
val, = struct.unpack('>H', sections[0][i:i+2])
if val >= hr.last_data_offset:
sections[0][i:i+2] = struct.pack('>H', last_data)
sections[0][24:26] = struct.pack('>H', 1) # Set has metadata
sections[0][44:46] = struct.pack('>H', last_data - 1) # Set location of metadata
sections[0][52:54] = struct.pack('>H', last_data) # Ensure last data offset is updated
# Merge the metadata into the file
file_mi = get_metadata(stream, False)
file_mi.smart_update(mi)
sections[hr.metadata_offset] = '%s\x00%s\x00%s\x00%s\x00%s\x00' % \
(file_mi.title, authors_to_string(file_mi.authors), '', file_mi.publisher, file_mi.isbn)
# Rebuild the PDB wrapper because the offsets have changed due to the
# new metadata.
pheader_builder = PdbHeaderBuilder(pheader.ident, pheader.title)
stream.seek(0)
stream.truncate(0)
pheader_builder.build_header([len(x) for x in sections], stream)
# Write the data back to the file
for item in sections:
stream.write(item)

View File

@ -12,11 +12,18 @@ import re
from calibre.ebooks.metadata import MetaInformation from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.pdb.header import PdbHeaderReader from calibre.ebooks.pdb.header import PdbHeaderReader
from calibre.ebooks.metadata.ereader import get_metadata as eReader from calibre.ebooks.metadata.ereader import get_metadata as get_eReader
MREADER = { MREADER = {
'PNPdPPrs' : eReader, 'PNPdPPrs' : get_eReader,
'PNRdPPrs' : eReader, 'PNRdPPrs' : get_eReader,
}
from calibre.ebooks.metadata.ereader import set_metadata as set_eReader
MWRITER = {
'PNPdPPrs' : set_eReader,
'PNRdPPrs' : set_eReader,
} }
def get_metadata(stream, extract_cover=True): def get_metadata(stream, extract_cover=True):
@ -34,3 +41,16 @@ def get_metadata(stream, extract_cover=True):
return MetadataReader(stream, extract_cover) return MetadataReader(stream, extract_cover)
def set_metadata(stream, mi):
stream.seek(0)
pheader = PdbHeaderReader(stream)
MetadataWriter = MWRITER.get(pheader.ident, None)
if MetadataWriter:
MetadataWriter(stream, mi)
stream.seek(0)
stream.write(re.sub('[^-A-Za-z0-9]+', '_', mi.title).ljust(32, '\x00')[:32])

View File

@ -12,7 +12,6 @@ import os, re, struct, zlib
from calibre import CurrentDir from calibre import CurrentDir
from calibre.ebooks import DRMError from calibre.ebooks import DRMError
from calibre.ebooks.metadata import MetaInformation
from calibre.ebooks.pdb.formatreader import FormatReader from calibre.ebooks.pdb.formatreader import FormatReader
from calibre.ebooks.pdb.ereader import EreaderError from calibre.ebooks.pdb.ereader import EreaderError
from calibre.ebooks.pml.pmlconverter import pml_to_html, \ from calibre.ebooks.pml.pmlconverter import pml_to_html, \
@ -31,6 +30,7 @@ class HeaderRecord(object):
def __init__(self, raw): def __init__(self, raw):
self.version, = struct.unpack('>H', raw[0:2]) self.version, = struct.unpack('>H', raw[0:2])
self.non_text_offset, = struct.unpack('>H', raw[12:14]) self.non_text_offset, = struct.unpack('>H', raw[12:14])
self.has_metadata, = struct.unpack('>H', raw[24:26])
self.footnote_rec, = struct.unpack('>H', raw[28:30]) self.footnote_rec, = struct.unpack('>H', raw[28:30])
self.sidebar_rec, = struct.unpack('>H', raw[30:32]) self.sidebar_rec, = struct.unpack('>H', raw[30:32])
self.bookmark_offset, = struct.unpack('>H', raw[32:34]) self.bookmark_offset, = struct.unpack('>H', raw[32:34])
@ -62,6 +62,9 @@ class Reader(FormatReader):
else: else:
raise EreaderError('Unknown book version %i.' % self.header_record.version) raise EreaderError('Unknown book version %i.' % self.header_record.version)
from calibre.ebooks.metadata.pdb import get_metadata
self.mi = get_metadata(stream, False)
def section_data(self, number): def section_data(self, number):
return self.sections[number] return self.sections[number]
@ -144,10 +147,8 @@ class Reader(FormatReader):
return opf_path return opf_path
def create_opf(self, output_dir, images): def create_opf(self, output_dir, images):
mi = MetaInformation(None, None)
with CurrentDir(output_dir): with CurrentDir(output_dir):
opf = OPFCreator(output_dir, mi) opf = OPFCreator(output_dir, self.mi)
manifest = [('index.html', None)] manifest = [('index.html', None)]

View File

@ -18,11 +18,7 @@ from calibre.ebooks.pdb.header import PdbHeaderBuilder
from calibre.ebooks.pdb.ereader import image_name from calibre.ebooks.pdb.ereader import image_name
from calibre.ebooks.pml.pmlconverter import html_to_pml from calibre.ebooks.pml.pmlconverter import html_to_pml
# We are using the older identity because we do not user newer features IDENTITY = 'PNRdPPrs'
# (sidebar, footnotes). This will ensure compatibility with older readers.
# If newer features are used (anything supported by dropbook but not by makebook
# change the identity to the newer PNRdPPrs.
IDENTITY = 'PNPdPPrs'
# This is an arbitrary number that is small enough to work. The actual maximum # This is an arbitrary number that is small enough to work. The actual maximum
# record size is unknown. # record size is unknown.

View File

@ -220,9 +220,11 @@ class DeviceManager(Thread):
'''Copy books from device to disk''' '''Copy books from device to disk'''
for path in paths: for path in paths:
name = path.rpartition('/')[2] name = path.rpartition('/')[2]
f = open(os.path.join(target, name), 'wb') dest = os.path.join(target, name)
self.device.get_file(path, f) if os.path.abspath(dest) != os.path.abspath(path):
f.close() f = open(dest, 'wb')
self.device.get_file(path, f)
f.close()
def save_books(self, done, paths, target): def save_books(self, done, paths, target):
return self.create_job(self._save_books, done, args=[paths, target], return self.create_job(self._save_books, done, args=[paths, target],
@ -493,6 +495,7 @@ class DeviceGUI(object):
return return
files, _auto_ids = self.library_view.model().get_preferred_formats_from_ids(ids, files, _auto_ids = self.library_view.model().get_preferred_formats_from_ids(ids,
fmts, paths=True, set_metadata=True, fmts, paths=True, set_metadata=True,
specific_format=specific_format,
exclude_auto=do_auto_convert) exclude_auto=do_auto_convert)
if do_auto_convert: if do_auto_convert:
ids = list(set(ids).difference(_auto_ids)) ids = list(set(ids).difference(_auto_ids))
@ -563,9 +566,9 @@ class DeviceGUI(object):
autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto] autos = [self.library_view.model().db.title(id, index_is_id=True) for id in auto]
autos = '\n'.join('%s'%i for i in autos) autos = '\n'.join('%s'%i for i in autos)
info_dialog(self, _('No suitable formats'), info_dialog(self, _('No suitable formats'),
_('Auto converting the following books before uploading to ' _('Auto converting the following books before sending via '
'the device:'), det_msg=autos, show=True) 'email:'), det_msg=autos, show=True)
self.auto_convert_mail(to, delete_from_library, auto, format) self.auto_convert_mail(to, fmts, delete_from_library, auto, format)
if bad: if bad:
bad = '\n'.join('%s'%(i,) for i in bad) bad = '\n'.join('%s'%(i,) for i in bad)

View File

@ -1051,7 +1051,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
current = self.library_view.currentIndex() current = self.library_view.currentIndex()
self.library_view.model().current_changed(current, previous) self.library_view.model().current_changed(current, previous)
def auto_convert_mail(self, to, delete_from_library, book_ids, format): def auto_convert_mail(self, to, fmts, delete_from_library, book_ids, format):
previous = self.library_view.currentIndex() previous = self.library_view.currentIndex()
rows = [x.row() for x in \ rows = [x.row() for x in \
self.library_view.selectionModel().selectedRows()] self.library_view.selectionModel().selectedRows()]
@ -1062,7 +1062,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
job = self.job_manager.run_job(Dispatcher(self.book_auto_converted_mail), job = self.job_manager.run_job(Dispatcher(self.book_auto_converted_mail),
func, args=args, description=desc) func, args=args, description=desc)
self.conversion_jobs[job] = (temp_files, fmt, id, self.conversion_jobs[job] = (temp_files, fmt, id,
delete_from_library, to) delete_from_library, to, fmts)
if changed: if changed:
self.library_view.model().refresh_rows(rows) self.library_view.model().refresh_rows(rows)
@ -1141,7 +1141,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.sync_to_device(on_card, False, specific_format=fmt, send_ids=[book_id], do_auto_convert=False) self.sync_to_device(on_card, False, specific_format=fmt, send_ids=[book_id], do_auto_convert=False)
def book_auto_converted_mail(self, job): def book_auto_converted_mail(self, job):
temp_files, fmt, book_id, delete_from_library, to = self.conversion_jobs.pop(job) temp_files, fmt, book_id, delete_from_library, to, fmts = self.conversion_jobs.pop(job)
try: try:
if job.failed: if job.failed:
self.job_exception(job) self.job_exception(job)
@ -1162,7 +1162,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
current = self.library_view.currentIndex() current = self.library_view.currentIndex()
self.library_view.model().current_changed(current, QModelIndex()) self.library_view.model().current_changed(current, QModelIndex())
self.send_by_mail(to, fmt, delete_from_library, send_ids=[book_id], do_auto_convert=False) self.send_by_mail(to, fmts, delete_from_library, specific_format=fmt, send_ids=[book_id], do_auto_convert=False)
def book_converted(self, job): def book_converted(self, job):
temp_files, fmt, book_id = self.conversion_jobs.pop(job) temp_files, fmt, book_id = self.conversion_jobs.pop(job)