diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py
index 6299bb8782..9e18af3cf9 100644
--- a/src/calibre/__init__.py
+++ b/src/calibre/__init__.py
@@ -246,7 +246,7 @@ class CurrentDir(object):
os.chdir(self.cwd)
-class FileWrapper(object):
+class StreamReadWrapper(object):
'''
Used primarily with pyPdf to ensure the stream is properly closed.
'''
diff --git a/src/calibre/ebooks/conversion/preprocess.py b/src/calibre/ebooks/conversion/preprocess.py
index 632a7a3291..b105a6c042 100644
--- a/src/calibre/ebooks/conversion/preprocess.py
+++ b/src/calibre/ebooks/conversion/preprocess.py
@@ -23,6 +23,14 @@ def sanitize_head(match):
x = _span_pat.sub('', x)
return '
\n'+x+'\n'
+def chap_head(match):
+ chap = match.group('chap')
+ title = match.group('title')
+ if not title:
+ return '', re.IGNORECASE), lambda match: '
'),
# Remove page numbers
(re.compile(r'\d+
', re.IGNORECASE), lambda match: ''),
- # Remove
and replace
with
+ # Replace
with
(re.compile(r'\s*', re.IGNORECASE), lambda match: ''),
+ # Remove
(re.compile(r'(.*)', re.IGNORECASE),
lambda match: match.group() if \
re.match('<', match.group(1).lstrip()) or \
@@ -69,15 +78,22 @@ class HTMLPreProcessor(object):
# Remove non breaking spaces
(re.compile(ur'\u00a0'), lambda match : ' '),
+ # Detect Chapters to match default XPATH in GUI
+ (re.compile(r'(
]*>)?(?p[^>]*>)?s*(?P(Chapter|Epilogue|Prologue|Book|Part)\s*(\d+|\w+)?)(?p[^>]*>|
]*>)\n?((?=()?\s*\w+(\s+\w+)?()?(
]*>|?p[^>]*>))((?P.*)(
]*>|?p[^>]*>)))?', re.IGNORECASE), chap_head),
+ (re.compile(r'(
]*>)?(?p[^>]*>)?s*(?P([A-Z \'"!]{5,})\s*(\d+|\w+)?)(?p[^>]*>|
]*>)\n?((?=()?\s*\w+(\s+\w+)?()?(
]*>|?p[^>]*>))((?P.*)(
]*>|?p[^>]*>)))?'), chap_head),
+
# Have paragraphs show better
(re.compile(r''), lambda match : ''),
# Un wrap lines
- (re.compile(r'(?<=\w)\s*(i|b|u)>\s*
\s*<(i|b|u)>\s*(?=\w)'), lambda match: ' '),
- (re.compile(r'(?<=\w)\s*\s*(?=\w)', re.UNICODE), lambda match: ' '),
+ (re.compile(r'(?<=[^\.^\^?^!^"^”])\s*((i|b|u)>)*\s*\s*(<(i|b|u)>)*\s*(?=[a-z0-9I])', re.UNICODE), lambda match: ' '),
+
# Clean up spaces
- (re.compile(u'(?<=\.|,|:|;|\?|!|”|"|\')[\s^ ]*(?=<)'), lambda match: ' '),
- ]
+ (re.compile(u'(?<=[\.,:;\?!”"\'])[\s^ ]*(?=<)'), lambda match: ' '),
+ # Add space before and after italics
+ (re.compile(r'(?'), lambda match: ' '),
+ (re.compile(r'(?=\w)'), lambda match: ' '),
+ ]
# Fix Book Designer markup
BOOK_DESIGNER = [
diff --git a/src/calibre/ebooks/metadata/pdf.py b/src/calibre/ebooks/metadata/pdf.py
index 73d621661a..6bf8bba138 100644
--- a/src/calibre/ebooks/metadata/pdf.py
+++ b/src/calibre/ebooks/metadata/pdf.py
@@ -6,7 +6,7 @@ __copyright__ = '2008, Kovid Goyal '
import sys, os, cStringIO
from threading import Thread
-from calibre import FileWrapper
+from calibre import StreamReadWrapper
from calibre.ebooks.metadata import MetaInformation, authors_to_string
from calibre.ptempfile import TemporaryDirectory
from pyPdf import PdfFileReader, PdfFileWriter
@@ -33,7 +33,7 @@ def get_metadata(stream, extract_cover=True):
traceback.print_exc()
try:
- with FileWrapper(stream) as stream:
+ with StreamReadWrapper(stream) as stream:
info = PdfFileReader(stream).getDocumentInfo()
if info.title:
mi.title = info.title
@@ -94,29 +94,27 @@ def set_metadata(stream, mi):
stream.seek(0)
def get_cover(stream):
-
try:
- pdf = PdfFileReader(stream)
- output = PdfFileWriter()
-
- if len(pdf.pages) >= 1:
- output.addPage(pdf.getPage(0))
-
- with TemporaryDirectory('_pdfmeta') as tdir:
- cover_path = os.path.join(tdir, 'cover.pdf')
-
- with open(cover_path, "wb") as outputStream:
- output.write(outputStream)
- with ImageMagick():
- wand = NewMagickWand()
- MagickReadImage(wand, cover_path)
- MagickSetImageFormat(wand, 'JPEG')
- MagickWriteImage(wand, '%s.jpg' % cover_path)
- return open('%s.jpg' % cover_path, 'rb').read()
-
+ with StreamReadWrapper(stream) as stream:
+ pdf = PdfFileReader(stream)
+ output = PdfFileWriter()
+
+ if len(pdf.pages) >= 1:
+ output.addPage(pdf.getPage(0))
+
+ with TemporaryDirectory('_pdfmeta') as tdir:
+ cover_path = os.path.join(tdir, 'cover.pdf')
+
+ with open(cover_path, "wb") as outputStream:
+ output.write(outputStream)
+ with ImageMagick():
+ wand = NewMagickWand()
+ MagickReadImage(wand, cover_path)
+ MagickSetImageFormat(wand, 'JPEG')
+ MagickWriteImage(wand, '%s.jpg' % cover_path)
+ return open('%s.jpg' % cover_path, 'rb').read()
except:
import traceback
traceback.print_exc()
return ''
-
diff --git a/src/calibre/ebooks/pdf/writer.py b/src/calibre/ebooks/pdf/writer.py
index 0f8cbf50c0..f91dae44fd 100644
--- a/src/calibre/ebooks/pdf/writer.py
+++ b/src/calibre/ebooks/pdf/writer.py
@@ -126,7 +126,7 @@ class PDFWriter(QObject):
try:
outPDF = PdfFileWriter(title=self.metadata.title, author=self.metadata.author)
for item in self.combine_queue:
- inputPDF = PdfFileReader(file(item, 'rb'))
+ inputPDF = PdfFileReader(open(item, 'rb'))
for page in inputPDF.pages:
outPDF.addPage(page)
outPDF.write(self.out_stream)
diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py
index 8d1b7a1b3a..239fd4d37d 100644
--- a/src/calibre/gui2/device.py
+++ b/src/calibre/gui2/device.py
@@ -346,10 +346,25 @@ class DeviceMenu(QMenu):
self.action_triggered(action)
break
- def enable_device_actions(self, enable):
+ def enable_device_actions(self, enable, card_prefix=(None, None)):
for action in self.actions:
if action.dest in ('main:', 'carda:0', 'cardb:0'):
- action.setEnabled(enable)
+ if not enable:
+ action.setEnabled(False)
+ else:
+ if action.dest == 'main:':
+ action.setEnabled(True)
+ elif action.dest == 'carda:0':
+ if card_prefix[0] != None:
+ action.setEnabled(True)
+ else:
+ action.setEnabled(False)
+ elif action.dest == 'cardb:0':
+ if card_prefix[1] != None:
+ action.setEnabled(True)
+ else:
+ action.setEnabled(False)
+
class Emailer(Thread):
diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py
index 86d1b013e3..21d873db60 100644
--- a/src/calibre/gui2/main.py
+++ b/src/calibre/gui2/main.py
@@ -608,7 +608,7 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI):
self.device_manager.device.__class__.__name__+\
_(' detected.'), 3000)
self.device_connected = True
- self._sync_menu.enable_device_actions(True)
+ self._sync_menu.enable_device_actions(True, self.device_manager.device.card_prefix())
else:
self.device_connected = False
self._sync_menu.enable_device_actions(False)