From e9bf92ed0ea71132df7ef65000b82c02069b57e8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 27 May 2010 16:35:55 -0600 Subject: [PATCH 1/4] Use PNP drive number based sorting on windows when the device has identical main memory and card PROD ids --- resources/recipes/wired.recipe | 2 +- src/calibre/devices/__init__.py | 6 ++++-- src/calibre/devices/binatone/driver.py | 11 +---------- src/calibre/devices/eb600/driver.py | 9 --------- src/calibre/devices/edge/driver.py | 8 -------- src/calibre/devices/eslick/driver.py | 8 -------- src/calibre/devices/hanlin/driver.py | 26 -------------------------- src/calibre/devices/iriver/driver.py | 8 -------- src/calibre/devices/jetbook/driver.py | 8 -------- src/calibre/devices/nook/driver.py | 8 -------- src/calibre/devices/scanner.py | 19 +++++++++++++++++-- src/calibre/devices/teclast/driver.py | 11 ----------- src/calibre/devices/usbms/device.py | 25 +++++++++++++------------ src/calibre/ebooks/epub/output.py | 16 ++++++++++++++++ 14 files changed, 52 insertions(+), 113 deletions(-) diff --git a/resources/recipes/wired.recipe b/resources/recipes/wired.recipe index 33577447cc..d45d987f48 100644 --- a/resources/recipes/wired.recipe +++ b/resources/recipes/wired.recipe @@ -39,7 +39,7 @@ class Wired(BasicNewsRecipe): dict(name=['object','embed','iframe','link']) ,dict(name='div', attrs={'class':['podcast_storyboard','tweetmeme_button']}) ] - remove_attributes = ['height','width'] + remove_attributes = ['height','width'] def parse_index(self): diff --git a/src/calibre/devices/__init__.py b/src/calibre/devices/__init__.py index bcbd9b1640..1fe1ca7fcb 100644 --- a/src/calibre/devices/__init__.py +++ b/src/calibre/devices/__init__.py @@ -5,7 +5,7 @@ __copyright__ = '2008, Kovid Goyal ' Device drivers. ''' -import sys, time, pprint +import sys, time, pprint, operator from functools import partial from StringIO import StringIO @@ -54,7 +54,9 @@ def debug(ioreg_to_tmp=False, buf=None): if iswindows: drives = win_pnp_drives(debug=True) out('Drives detected:') - out(pprint.pformat(drives)) + for drive in sorted(drives.keys(), + key=operator.attrgetter('order')): + prints(u'\t(%d)'%drive.order, drive, '~', drives[drive]) ioreg = None if isosx: diff --git a/src/calibre/devices/binatone/driver.py b/src/calibre/devices/binatone/driver.py index aca08df27d..8b3c803901 100644 --- a/src/calibre/devices/binatone/driver.py +++ b/src/calibre/devices/binatone/driver.py @@ -35,19 +35,10 @@ class README(USBMS): SUPPORTS_SUB_DIRS = True - def windows_sort_drives(self, drives): - main = drives.get('main', None) - card = drives.get('carda', None) - if card and main and card < main: - drives['main'] = card - drives['carda'] = main - - return drives - def linux_swap_drives(self, drives): if len(drives) < 2: return drives drives = list(drives) t = drives[0] drives[0] = drives[1] drives[1] = t - return tuple(drives) \ No newline at end of file + return tuple(drives) diff --git a/src/calibre/devices/eb600/driver.py b/src/calibre/devices/eb600/driver.py index d0b6a8f345..307531c357 100644 --- a/src/calibre/devices/eb600/driver.py +++ b/src/calibre/devices/eb600/driver.py @@ -48,15 +48,6 @@ class EB600(USBMS): EBOOK_DIR_CARD_A = '' SUPPORTS_SUB_DIRS = True - def windows_sort_drives(self, drives): - main = drives.get('main', None) - card = drives.get('carda', None) - if card and main and card < main: - drives['main'] = card - drives['carda'] = main - - return drives - class COOL_ER(EB600): diff --git a/src/calibre/devices/edge/driver.py b/src/calibre/devices/edge/driver.py index 1c39531c37..d14763f313 100644 --- a/src/calibre/devices/edge/driver.py +++ b/src/calibre/devices/edge/driver.py @@ -36,12 +36,4 @@ class EDGE(USBMS): EBOOK_DIR_MAIN = 'download' SUPPORTS_SUB_DIRS = True - def windows_sort_drives(self, drives): - main = drives.get('main', None) - card = drives.get('carda', None) - if card and main and card < main: - drives['main'] = card - drives['carda'] = main - - return drives diff --git a/src/calibre/devices/eslick/driver.py b/src/calibre/devices/eslick/driver.py index 4854c5c730..a38f742ecf 100644 --- a/src/calibre/devices/eslick/driver.py +++ b/src/calibre/devices/eslick/driver.py @@ -36,12 +36,4 @@ class ESLICK(USBMS): SUPPORTS_SUB_DIRS = True - def windows_sort_drives(self, drives): - main = drives.get('main', None) - card = drives.get('carda', None) - if card and main and card < main: - drives['main'] = card - drives['carda'] = main - - return drives diff --git a/src/calibre/devices/hanlin/driver.py b/src/calibre/devices/hanlin/driver.py index dae1d39c05..49f9dfab57 100644 --- a/src/calibre/devices/hanlin/driver.py +++ b/src/calibre/devices/hanlin/driver.py @@ -39,23 +39,6 @@ class HANLINV3(USBMS): SUPPORTS_SUB_DIRS = True - def windows_sort_drives(self, drives): - main = drives.get('main', None) - card = drives.get('carda', None) - if card and main and card > main: - drives['main'] = card - drives['carda'] = main - - if card and not main: - drives['main'] = card - drives['carda'] = None - - return drives - - def windows_open_callback(self, drives): - if 'main' not in drives and 'carda' in drives: - drives['main'] = drives.pop('carda') - return drives def osx_sort_names(self, names): main = names.get('main', None) @@ -129,13 +112,4 @@ class BOOX(HANLINV3): EBOOK_DIR_CARD_A = 'MyBooks' - def windows_sort_drives(self, drives): - main = drives.get('main', None) - card = drives.get('carda', None) - if card and main and card < main: - drives['main'] = card - drives['carda'] = main - - return drives - diff --git a/src/calibre/devices/iriver/driver.py b/src/calibre/devices/iriver/driver.py index ca570eed7a..3dd94802c4 100644 --- a/src/calibre/devices/iriver/driver.py +++ b/src/calibre/devices/iriver/driver.py @@ -36,12 +36,4 @@ class IRIVER_STORY(USBMS): SUPPORTS_SUB_DIRS = True - def windows_open_callback(self, drives): - main = drives.get('main', None) - card = drives.get('carda', None) - if card and main and card < main: - drives['main'] = card - drives['carda'] = main - - return drives diff --git a/src/calibre/devices/jetbook/driver.py b/src/calibre/devices/jetbook/driver.py index e4fd840dc0..671fea5d75 100644 --- a/src/calibre/devices/jetbook/driver.py +++ b/src/calibre/devices/jetbook/driver.py @@ -80,11 +80,3 @@ class JETBOOK(USBMS): return mi - def windows_sort_drives(self, drives): - main = drives.get('main', None) - card = drives.get('carda', None) - if card and main and card < main: - drives['main'] = card - drives['carda'] = main - - return drives diff --git a/src/calibre/devices/nook/driver.py b/src/calibre/devices/nook/driver.py index 16bf9479d8..5793dc7187 100644 --- a/src/calibre/devices/nook/driver.py +++ b/src/calibre/devices/nook/driver.py @@ -77,14 +77,6 @@ class NOOK(USBMS): with open('%s.jpg' % os.path.join(path, filename), 'wb') as coverfile: coverfile.write(coverdata) - def windows_sort_drives(self, drives): - main = drives.get('main', None) - card = drives.get('carda', None) - if card and main and card < main: - drives['main'] = card - drives['carda'] = main - - return drives def sanitize_path_components(self, components): return [x.replace('#', '_') for x in components] diff --git a/src/calibre/devices/scanner.py b/src/calibre/devices/scanner.py index c47bdfb6fa..d8f9c90a17 100644 --- a/src/calibre/devices/scanner.py +++ b/src/calibre/devices/scanner.py @@ -5,7 +5,7 @@ Device scanner that fetches list of devices on system ina platform dependent manner. ''' -import sys, os +import sys, os, re from threading import RLock from calibre import iswindows, isosx, plugins, islinux @@ -23,6 +23,14 @@ elif isosx: except: raise RuntimeError('Failed to load the usbobserver plugin: %s'%plugins['usbobserver'][1]) +class Drive(str): + + def __new__(self, val, order=0): + typ = str.__new__(self, val) + typ.order = order + return typ + + class WinPNPScanner(object): def __init__(self): @@ -45,6 +53,13 @@ class WinPNPScanner(object): finally: win32api.SetErrorMode(oldError) + def drive_order(self, pnp_id): + order = 0 + match = re.search(r'REV_.*?&(\d+)', pnp_id) + if match is not None: + order = int(pnp_id) + return order + def __call__(self, debug=False): if self.scanner is None: return {} @@ -66,7 +81,7 @@ class WinPNPScanner(object): val = [x.upper() for x in val] val = [x for x in val if 'USBSTOR' in x] if val: - ans[key+':\\'] = val[-1] + ans[Drive(key+':\\', order=self.drive_order(val[-1]))] = val[-1] return ans win_pnp_drives = WinPNPScanner() diff --git a/src/calibre/devices/teclast/driver.py b/src/calibre/devices/teclast/driver.py index afc852816c..1701696fad 100644 --- a/src/calibre/devices/teclast/driver.py +++ b/src/calibre/devices/teclast/driver.py @@ -30,14 +30,6 @@ class TECLAST_K3(USBMS): EBOOK_DIR_CARD_A = '' SUPPORTS_SUB_DIRS = True - def windows_sort_drives(self, drives): - main = drives.get('main', None) - card = drives.get('carda', None) - if card and main and card < main: - drives['main'] = card - drives['carda'] = main - - return drives class NEWSMY(TECLAST_K3): name = 'Newsmy device interface' @@ -50,9 +42,6 @@ class NEWSMY(TECLAST_K3): WINDOWS_MAIN_MEM = 'NEWSMY' WINDOWS_CARD_A_MEM = 'USBDISK____SD' - def windows_sort_drives(self, drives): - return drives - class IPAPYRUS(TECLAST_K3): name = 'iPapyrus device interface' diff --git a/src/calibre/devices/usbms/device.py b/src/calibre/devices/usbms/device.py index 897baf82ca..7b85eae93e 100644 --- a/src/calibre/devices/usbms/device.py +++ b/src/calibre/devices/usbms/device.py @@ -11,13 +11,7 @@ intended to be subclassed with the relevant parts implemented for a particular device. This class handles device detection. ''' -import os -import subprocess -import time -import re -import sys -import glob - +import os, subprocess, time, re, sys, glob, operator from itertools import repeat from calibre.devices.interface import DevicePlugin @@ -62,6 +56,8 @@ class Device(DeviceConfig, DevicePlugin): BCD = None VENDOR_NAME = None + + # These can be None, string, list of strings or compiled regex WINDOWS_MAIN_MEM = None WINDOWS_CARD_A_MEM = None WINDOWS_CARD_B_MEM = None @@ -245,21 +241,26 @@ class Device(DeviceConfig, DevicePlugin): drives.get('main', None) is None: drives['main'] = drives.pop('carda') - drives = self.windows_open_callback(drives) - if drives.get('main', None) is None: raise DeviceError( _('Unable to detect the %s disk drive. Try rebooting.') % self.__class__.__name__) + # Sort drives by their PNP drive numbers if the CARD and MAIN + # MEM strings are identical + if self.WINDOWS_MAIN_MEM in (self.WINDOWS_CARD_A_MEM, + self.WINDOWS_CARD_B_MEM) or \ + self.WINDOWS_CARD_A_MEM == self.WINDOWS_CARD_B_MEM: + letters = sorted(drives.values(), key=operator.itemgetter('order')) + drives = {} + for which, letter in zip(['main', 'carda', 'cardb'], letters): + drives[which] = letter + drives = self.windows_sort_drives(drives) self._main_prefix = drives.get('main') self._card_a_prefix = drives.get('carda', None) self._card_b_prefix = drives.get('cardb', None) - def windows_open_callback(self, drives): - return drives - @classmethod def run_ioreg(cls, raw=None): if raw is not None: diff --git a/src/calibre/ebooks/epub/output.py b/src/calibre/ebooks/epub/output.py index 47d06c2255..180b0c1f23 100644 --- a/src/calibre/ebooks/epub/output.py +++ b/src/calibre/ebooks/epub/output.py @@ -121,11 +121,27 @@ class EPUBOutput(OutputFormatPlugin): if not pre.text and len(pre) == 0: pre.tag = 'div' + def upshift_markup(self): + 'Upgrade markup to comply with XHTML 1.1 where possible' + from calibre.ebooks.oeb.base import XPath + 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 + for u in XPath('//h:u')(root): + u.tag = 'span' + u.set('style', 'text-decoration:underline') + def convert(self, oeb, output_path, input_plugin, opts, log): self.log, self.opts, self.oeb = log, opts, oeb self.workaround_ade_quirks() self.workaround_webkit_quirks() + self.upshift_markup() from calibre.ebooks.oeb.transforms.rescale import RescaleImages RescaleImages()(oeb, opts) From 9d7907fc29ab9bdefd3ed6c5bd24623a212b3089 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 27 May 2010 20:44:24 -0600 Subject: [PATCH 2/4] Fix #5621 (Tooltips and GTK theme) --- src/calibre/gui2/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index 4c75758567..aa17979d7d 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -556,6 +556,7 @@ class Application(QApplication): border-radius: 10px; opacity: 200; background-color: #e1e1ff; + color: black; } ''') From 352ea8642809c9c3e70c8106fef3ae50c661a82c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 27 May 2010 23:41:16 -0600 Subject: [PATCH 3/4] ... --- src/calibre/devices/scanner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/devices/scanner.py b/src/calibre/devices/scanner.py index d8f9c90a17..ceba5d37d0 100644 --- a/src/calibre/devices/scanner.py +++ b/src/calibre/devices/scanner.py @@ -57,7 +57,7 @@ class WinPNPScanner(object): order = 0 match = re.search(r'REV_.*?&(\d+)', pnp_id) if match is not None: - order = int(pnp_id) + order = int(match.group(1)) return order def __call__(self, debug=False): From 5ea351492a3e72def50fb84c5951513f3ad3792f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Thu, 27 May 2010 23:49:27 -0600 Subject: [PATCH 4/4] ... --- src/calibre/devices/usbms/device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/devices/usbms/device.py b/src/calibre/devices/usbms/device.py index 7b85eae93e..96a5fc0b43 100644 --- a/src/calibre/devices/usbms/device.py +++ b/src/calibre/devices/usbms/device.py @@ -251,7 +251,7 @@ class Device(DeviceConfig, DevicePlugin): if self.WINDOWS_MAIN_MEM in (self.WINDOWS_CARD_A_MEM, self.WINDOWS_CARD_B_MEM) or \ self.WINDOWS_CARD_A_MEM == self.WINDOWS_CARD_B_MEM: - letters = sorted(drives.values(), key=operator.itemgetter('order')) + letters = sorted(drives.values(), key=operator.attrgetter('order')) drives = {} for which, letter in zip(['main', 'carda', 'cardb'], letters): drives[which] = letter