Kindle driver: Add an option to allow using page counts stored in a custom column. Go to Preferences->Plugins and customize the Kindle driver, to tell it to use a custom column to get page count data.

This commit is contained in:
Kovid Goyal 2012-02-11 10:23:41 +05:30
parent 0b4f34cb2d
commit bd27557d58
3 changed files with 65 additions and 12 deletions

View File

@ -19,7 +19,12 @@ class APNXBuilder(object):
Create an APNX file using a pseudo page mapping. Create an APNX file using a pseudo page mapping.
''' '''
def write_apnx(self, mobi_file_path, apnx_path, accurate=True): def write_apnx(self, mobi_file_path, apnx_path, accurate=True, page_count=0):
'''
If you want a fixed number of pages (such as from a custom column) then
pass in a value to page_count, otherwise a count will be estimated
using either the fast or accurate algorithm.
'''
# Check that this is really a MOBI file. # Check that this is really a MOBI file.
with open(mobi_file_path, 'rb') as mf: with open(mobi_file_path, 'rb') as mf:
ident = PdbHeaderReader(mf).identity() ident = PdbHeaderReader(mf).identity()
@ -28,6 +33,9 @@ class APNXBuilder(object):
# Get the pages depending on the chosen parser # Get the pages depending on the chosen parser
pages = [] pages = []
if page_count:
pages = self.get_pages_exact(mobi_file_path, page_count)
else:
if accurate: if accurate:
try: try:
pages = self.get_pages_accurate(mobi_file_path) pages = self.get_pages_accurate(mobi_file_path)
@ -77,6 +85,31 @@ class APNXBuilder(object):
return apnx return apnx
def get_pages_exact(self, mobi_file_path, page_count):
'''
Given a specified page count (such as from a custom column),
create our array of pages for the apnx file by dividing by
the content size of the book.
'''
pages = []
count = 0
with open(mobi_file_path, 'rb') as mf:
phead = PdbHeaderReader(mf)
r0 = phead.section_data(0)
text_length = struct.unpack('>I', r0[4:8])[0]
chars_per_page = int(text_length / page_count)
while count < text_length:
pages.append(count)
count += chars_per_page
if len(pages) > page_count:
# Rounding created extra page entries
pages = pages[:page_count]
return pages
def get_pages_fast(self, mobi_file_path): def get_pages_fast(self, mobi_file_path):
''' '''
2300 characters of uncompressed text per page. This is 2300 characters of uncompressed text per page. This is

View File

@ -302,19 +302,28 @@ class KINDLE2(KINDLE):
' this information to the Kindle when uploading MOBI files by' ' this information to the Kindle when uploading MOBI files by'
' USB. Note that the page numbers do not correspond to any paper' ' USB. Note that the page numbers do not correspond to any paper'
' book.'), ' book.'),
_('Use slower but more accurate page number generation') + _('Use slower but more accurate page number calculation') +
':::' + ':::' +
_('There are two ways to generate the page number information. Using the more accurate ' _('There are two ways to generate the page number information. Using the more accurate '
'generator will produce pages that correspond better to a printed book. ' 'generator will produce pages that correspond better to a printed book. '
'However, this method is slower and will slow down sending files ' 'However, this method is slower and will slow down sending files '
'to the Kindle.'), 'to the Kindle.'),
_('Custom column name to retrieve page counts from') +
':::' +
_('If you have a custom column in your library that you use to '
'store the page count of books, you can have calibre use that '
'information, instead of calculating a page count. Specify the '
'name of the custom column here, for example, #pages. '),
] ]
EXTRA_CUSTOMIZATION_DEFAULT = [ EXTRA_CUSTOMIZATION_DEFAULT = [
True, True,
False, False,
'',
] ]
OPT_APNX = 0 OPT_APNX = 0
OPT_APNX_ACCURATE = 1 OPT_APNX_ACCURATE = 1
OPT_APNX_CUST_COL = 2
def books(self, oncard=None, end_session=True): def books(self, oncard=None, end_session=True):
bl = USBMS.books(self, oncard=oncard, end_session=end_session) bl = USBMS.books(self, oncard=oncard, end_session=end_session)
@ -380,10 +389,20 @@ class KINDLE2(KINDLE):
if not os.path.exists(path): if not os.path.exists(path):
os.makedirs(path) os.makedirs(path)
cust_col_name = opts.extra_customization[self.OPT_APNX_CUST_COL]
custom_page_count = 0
if cust_col_name:
try:
custom_page_count = int(metadata.get(cust_col_name, 0))
except:
pass
apnx_path = '%s.apnx' % os.path.join(path, filename) apnx_path = '%s.apnx' % os.path.join(path, filename)
apnx_builder = APNXBuilder() apnx_builder = APNXBuilder()
try: try:
apnx_builder.write_apnx(filepath, apnx_path, accurate=opts.extra_customization[self.OPT_APNX_ACCURATE]) apnx_builder.write_apnx(filepath, apnx_path,
accurate=opts.extra_customization[self.OPT_APNX_ACCURATE],
page_count=custom_page_count)
except: except:
print 'Failed to generate APNX' print 'Failed to generate APNX'
import traceback import traceback

View File

@ -82,6 +82,7 @@ class ConfigWidget(QWidget, Ui_ConfigWidget):
self.opt_extra_customization.append(QLineEdit(self)) self.opt_extra_customization.append(QLineEdit(self))
l = QLabel(label_text) l = QLabel(label_text)
l.setToolTip(tt) l.setToolTip(tt)
self.opt_extra_customization[i].setToolTip(tt)
l.setBuddy(self.opt_extra_customization[i]) l.setBuddy(self.opt_extra_customization[i])
l.setWordWrap(True) l.setWordWrap(True)
self.opt_extra_customization[i].setText(settings.extra_customization[i]) self.opt_extra_customization[i].setText(settings.extra_customization[i])