From 71d038d975f6605bea97eca555c48ad756a48c69 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 28 Mar 2011 15:29:17 -0600 Subject: [PATCH 1/5] EPUB Output: Remove any margins specified via an Adobe page template in the input document --- src/calibre/ebooks/conversion/plumber.py | 4 +- src/calibre/ebooks/oeb/transforms/margins.py | 56 ------------------- .../ebooks/oeb/transforms/page_margin.py | 20 +++++++ 3 files changed, 23 insertions(+), 57 deletions(-) delete mode 100644 src/calibre/ebooks/oeb/transforms/margins.py diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py index 6272e7b10b..b26befe075 100644 --- a/src/calibre/ebooks/conversion/plumber.py +++ b/src/calibre/ebooks/conversion/plumber.py @@ -1003,8 +1003,10 @@ OptionRecommendation(name='sr3_replace', self.opts.insert_blank_line = oibl self.opts.remove_paragraph_spacing = orps - from calibre.ebooks.oeb.transforms.page_margin import RemoveFakeMargins + from calibre.ebooks.oeb.transforms.page_margin import \ + RemoveFakeMargins, RemoveAdobeMargins RemoveFakeMargins()(self.oeb, self.log, self.opts) + RemoveAdobeMargins()(self.oeb, self.log, self.opts) pr(0.9) self.flush() diff --git a/src/calibre/ebooks/oeb/transforms/margins.py b/src/calibre/ebooks/oeb/transforms/margins.py deleted file mode 100644 index fbdf2e63fd..0000000000 --- a/src/calibre/ebooks/oeb/transforms/margins.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai - -__license__ = 'GPL v3' -__copyright__ = '2010, Kovid Goyal ' -__docformat__ = 'restructuredtext en' - - -class RemoveFakeMargins(object): - ''' - Try to detect and remove fake margins inserted by asinine ebook creation - software on each paragraph/wrapper div. Can be used only after CSS - flattening. - ''' - - def __call__(self, oeb, opts, log): - self.oeb, self.opts, self.log = oeb, opts, log - - from calibre.ebooks.oeb.base import XPath, OEB_STYLES - - stylesheet = None - for item in self.oeb.manifest: - if item.media_type.lower() in OEB_STYLES: - stylesheet = item.data - break - - if stylesheet is None: - return - - - top_level_elements = {} - second_level_elements = {} - - for x in self.oeb.spine: - root = x.data - body = XPath('//h:body')(root) - if body: - body = body[0] - - if not hasattr(body, 'xpath'): - continue - - # Check for margins on top level elements - for lb in XPath('./h:div|./h:p|./*/h:div|./*/h:p')(body): - cls = lb.get('class', '') - level = top_level_elements if lb.getparent() is body else \ - second_level_elements - if cls not in level: - level[cls] = [] - top_level_elements[cls] = [] - level[cls].append(lb) - - - def get_margins(self, stylesheet, cls): - pass - diff --git a/src/calibre/ebooks/oeb/transforms/page_margin.py b/src/calibre/ebooks/oeb/transforms/page_margin.py index 589f004dd1..c415dda0e0 100644 --- a/src/calibre/ebooks/oeb/transforms/page_margin.py +++ b/src/calibre/ebooks/oeb/transforms/page_margin.py @@ -11,6 +11,26 @@ from collections import Counter from calibre.ebooks.oeb.base import OEB_STYLES, barename, XPath +class RemoveAdobeMargins(object): + ''' + Remove margins specified in Adobe's page templates. + ''' + + def __call__(self, oeb, log, opts): + self.oeb, self.opts, self.log = oeb, opts, log + + for item in self.oeb.manifest: + if item.media_type == 'application/vnd.adobe-page-template+xml': + self.log('Removing page margins specified in the' + ' Adobe page template') + for elem in item.data.xpath( + '//*[@margin-bottom or @margin-top ' + 'or @margin-left or @margin-right]'): + for margin in ('left', 'right', 'top', 'bottom'): + attr = 'margin-'+margin + elem.attrib.pop(attr, None) + + class RemoveFakeMargins(object): ''' From eb38a529df6241158371f84d68dd49469de61dac Mon Sep 17 00:00:00 2001 From: GRiker Date: Mon, 28 Mar 2011 14:58:10 -0700 Subject: [PATCH 2/5] GwR patch supporting new user Apple driver disabling --- src/calibre/devices/apple/driver.py | 81 +++++++++++++++++++++-------- src/calibre/devices/errors.py | 4 +- src/calibre/gui2/device.py | 2 +- 3 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/calibre/devices/apple/driver.py b/src/calibre/devices/apple/driver.py index c12b533c4e..ed26ae86e1 100644 --- a/src/calibre/devices/apple/driver.py +++ b/src/calibre/devices/apple/driver.py @@ -17,35 +17,75 @@ from calibre.ebooks.metadata import authors_to_string, MetaInformation, \ title_sort from calibre.ebooks.metadata.book.base import Metadata from calibre.ebooks.metadata.epub import set_metadata +from calibre.gui2.dialogs.confirm_delete import _config_name from calibre.library.server.utils import strftime -from calibre.utils.config import config_dir, prefs +from calibre.utils.config import config_dir, dynamic, DynamicConfig, prefs from calibre.utils.date import now, parse_date from calibre.utils.logging import Log from calibre.utils.zipfile import ZipFile - class AppleOpenFeedback(OpenFeedback): - def __init__(self): + def __init__(self, plugin): OpenFeedback.__init__(self, u'') + self.log = plugin.log + self.plugin = plugin def custom_dialog(self, parent): - from PyQt4.Qt import (QDialog, QVBoxLayout, QLabel, QDialogButtonBox) + from PyQt4.Qt import (QCheckBox, QDialog, QDialogButtonBox, QIcon, + QLabel, QPixmap, QPushButton, QSize, QVBoxLayout) class Dialog(QDialog): - def __init__(self, p): + def __init__(self, p, pixmap='dialog_information.png'): QDialog.__init__(self, p) + + self.setWindowTitle("Apple iDevice detected") self.l = l = QVBoxLayout() self.setLayout(l) - l.addWidget(QLabel('test')) - self.bb = QDialogButtonBox(QDialogButtonBox.OK) + msg = QLabel() + msg.setText( + '

If you do not want calibre to recognize your Apple iDevice ' + 'when it is connected to your computer, ' + 'click Disable Apple Driver.

' + '

To transfer books to your iDevice, ' + 'click Disable Apple Driver, ' + "then use the 'Connect to iTunes' method recommended in the " + 'Calibre + iDevices FAQ, ' + 'using the Connect/Share|Connect to iTunes menu item.

' + '

Enabling the Apple driver for direct connection to iDevices ' + 'is an unsupported advanced user mode.

' + '

' + ) + msg.setWordWrap(True) + l.addWidget(msg) + + self.bb = QDialogButtonBox() + disable_driver = QPushButton(_("Disable Apple driver")) + disable_driver.setDefault(True) + self.bb.addButton(disable_driver, QDialogButtonBox.RejectRole) + + enable_driver = QPushButton(_("Enable Apple driver")) + self.bb.addButton(enable_driver, QDialogButtonBox.AcceptRole) l.addWidget(self.bb) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) - return Dialog(parent) + self.setWindowIcon(QIcon(I(pixmap))) + self.resize(self.sizeHint()) + + if Dialog(parent).exec_(): + # Enable Apple driver, inhibit future display of dialog + # Reset dialog with Preferences|Behavior|Reset all disabled confirmation dialogs + self.log.info(" Apple driver ENABLED") + dynamic[_config_name(self.plugin.DISPLAY_DISABLE_DIALOG)] = False + else: + # Disable Apple driver + from calibre.customize.ui import disable_plugin + self.log.info(" Apple driver DISABLED") + disable_plugin(self.plugin) + from PIL import Image as PILImage from lxml import etree @@ -77,15 +117,11 @@ class DriverBase(DeviceConfig, DevicePlugin): 'iBooks Category'), _('Cache covers from iTunes/iBooks') + ':::' + - _('Enable to cache and display covers from iTunes/iBooks'), - _("Skip 'Connect to iTunes' recommendation") + - ':::' + - _("Enable to skip the 'Connect to iTunes' recommendation dialog") + _('Enable to cache and display covers from iTunes/iBooks') ] EXTRA_CUSTOMIZATION_DEFAULT = [ True, True, - False, ] @@ -141,12 +177,13 @@ class ITUNES(DriverBase): supported_platforms = ['osx','windows'] author = 'GRiker' #: The version of this plugin as a 3-tuple (major, minor, revision) - version = (0,9,0) + version = (1,0,0) + + DISPLAY_DISABLE_DIALOG = "display_disable_dialog" # EXTRA_CUSTOMIZATION_MESSAGE indexes USE_SERIES_AS_CATEGORY = 0 CACHE_COVERS = 1 - SKIP_CONNECT_TO_ITUNES_DIALOG = 2 OPEN_FEEDBACK_MESSAGE = _( 'Apple device detected, launching iTunes, please wait ...') @@ -762,15 +799,17 @@ class ITUNES(DriverBase): Note that most of the initialization is necessarily performed in can_handle(), as we need to talk to iTunes to discover if there's a connected iPod ''' + if DEBUG: self.log.info("ITUNES.open()") - # Display a dialog recommending using 'Connect to iTunes' - if not self.settings().extra_customization[self.SKIP_CONNECT_TO_ITUNES_DIALOG]: - raise AppleOpenFeedback() - - if DEBUG: - self.log.info(" advanced user mode, directly connecting to iDevice") + # Display a dialog recommending using 'Connect to iTunes' if user hasn't + # previously disabled the dialog + if dynamic.get(_config_name(self.DISPLAY_DISABLE_DIALOG),True): + raise AppleOpenFeedback(self) + else: + if DEBUG: + self.log.info(" advanced user mode, directly connecting to iDevice") # Confirm/create thumbs archive if not os.path.exists(self.cache_dir): diff --git a/src/calibre/devices/errors.py b/src/calibre/devices/errors.py index 7b11b6933f..05c30c2f72 100644 --- a/src/calibre/devices/errors.py +++ b/src/calibre/devices/errors.py @@ -43,8 +43,8 @@ class OpenFeedback(DeviceError): def custom_dialog(self, parent): ''' - If you need to show the user a custom dialog, instead if just - displaying the feedback_msg, create and return it here. + If you need to show the user a custom dialog, create and + run it from a custom_dialog() method in your subclass. ''' raise NotImplementedError diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 6163c01d27..39a638850d 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -623,7 +623,7 @@ class DeviceMixin(object): # {{{ self.__of_dev_mem__ = d = e.custom_dialog(self) except NotImplementedError: self.__of_dev_mem__ = d = info_dialog(self, devname, e.feedback_msg) - d.show() + d.show() def auto_convert_question(self, msg, autos): autos = u'\n'.join(map(unicode, map(force_unicode, autos))) From 833f46b1496ba6daaee527cbcc3f4eae6d919ea6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 28 Mar 2011 16:26:54 -0600 Subject: [PATCH 3/5] ... --- src/calibre/ebooks/metadata/sources/identify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/metadata/sources/identify.py b/src/calibre/ebooks/metadata/sources/identify.py index 53fb3a9ea4..5bc0c5b256 100644 --- a/src/calibre/ebooks/metadata/sources/identify.py +++ b/src/calibre/ebooks/metadata/sources/identify.py @@ -79,7 +79,7 @@ def identify(log, abort, title=None, authors=None, identifiers=[], timeout=30): time.sleep(0.2) if get_results() and first_result_at is None: - first_result_at = time.time() + first_result_at = time.time() if not is_worker_alive(workers): break From 4952ef92ec5fe7fb781cdaba5c039ebd6d6d9ad1 Mon Sep 17 00:00:00 2001 From: GRiker Date: Mon, 28 Mar 2011 16:03:30 -0700 Subject: [PATCH 4/5] GwR patches supporting dynamic disabling of Apple driver V2 --- src/calibre/devices/apple/driver.py | 14 +++++++------- src/calibre/devices/errors.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/calibre/devices/apple/driver.py b/src/calibre/devices/apple/driver.py index 7a9562f136..2dc095507c 100644 --- a/src/calibre/devices/apple/driver.py +++ b/src/calibre/devices/apple/driver.py @@ -38,9 +38,9 @@ class AppleOpenFeedback(OpenFeedback): class Dialog(QDialog): - def __init__(self, p, pixmap='dialog_information.png'): + def __init__(self, p, cd, pixmap='dialog_information.png'): QDialog.__init__(self, p) - + self.cd = cd self.setWindowTitle("Apple iDevice detected") self.l = l = QVBoxLayout() self.setLayout(l) @@ -80,14 +80,14 @@ class AppleOpenFeedback(OpenFeedback): def do_it(self, return_code): if return_code == self.Accepted: - self.log.info(" Apple driver ENABLED") - dynamic[config_name(self.plugin.DISPLAY_DISABLE_DIALOG)] = False + self.cd.log.info(" Apple driver ENABLED") + dynamic[config_name(self.cd.plugin.DISPLAY_DISABLE_DIALOG)] = False else: from calibre.customize.ui import disable_plugin - self.log.info(" Apple driver DISABLED") - disable_plugin(self.plugin) + self.cd.log.info(" Apple driver DISABLED") + disable_plugin(self.cd.plugin) - return Dialog(parent) + return Dialog(parent, self) from PIL import Image as PILImage diff --git a/src/calibre/devices/errors.py b/src/calibre/devices/errors.py index 7b11b6933f..ecd61a1169 100644 --- a/src/calibre/devices/errors.py +++ b/src/calibre/devices/errors.py @@ -43,7 +43,7 @@ class OpenFeedback(DeviceError): def custom_dialog(self, parent): ''' - If you need to show the user a custom dialog, instead if just + If you need to show the user a custom dialog, instead of just displaying the feedback_msg, create and return it here. ''' raise NotImplementedError From 1e82b4fcefa9a2257a2bcb98a3c840237966bb2b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 28 Mar 2011 17:04:05 -0600 Subject: [PATCH 5/5] ... --- src/calibre/devices/apple/driver.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/calibre/devices/apple/driver.py b/src/calibre/devices/apple/driver.py index 7a9562f136..7ede6dbf36 100644 --- a/src/calibre/devices/apple/driver.py +++ b/src/calibre/devices/apple/driver.py @@ -17,7 +17,6 @@ from calibre.ebooks.metadata import authors_to_string, MetaInformation, \ title_sort from calibre.ebooks.metadata.book.base import Metadata from calibre.ebooks.metadata.epub import set_metadata -from calibre.gui2.dialogs.confirm_delete import config_name from calibre.library.server.utils import strftime from calibre.utils.config import config_dir, dynamic, prefs from calibre.utils.date import now, parse_date @@ -80,6 +79,7 @@ class AppleOpenFeedback(OpenFeedback): def do_it(self, return_code): if return_code == self.Accepted: + from calibre.gui2.dialogs.confirm_delete import config_name self.log.info(" Apple driver ENABLED") dynamic[config_name(self.plugin.DISPLAY_DISABLE_DIALOG)] = False else: @@ -808,6 +808,7 @@ class ITUNES(DriverBase): # Display a dialog recommending using 'Connect to iTunes' if user hasn't # previously disabled the dialog + from calibre.gui2.dialogs.confirm_delete import config_name if dynamic.get(config_name(self.DISPLAY_DISABLE_DIALOG),True): raise AppleOpenFeedback(self) else: