diff --git a/src/calibre/devices/__init__.py b/src/calibre/devices/__init__.py index 3fead7b75f..4f71d39651 100644 --- a/src/calibre/devices/__init__.py +++ b/src/calibre/devices/__init__.py @@ -37,6 +37,10 @@ def debug(ioreg_to_tmp=False, buf=None): if buf is None: buf = StringIO() sys.stdout = sys.stderr = buf + if iswindows: + import pythoncom + pythoncom.CoInitialize() + try: out = partial(prints, file=buf) out('Version:', __version__) @@ -50,29 +54,25 @@ def debug(ioreg_to_tmp=False, buf=None): d[i] = hex(d[i]) out('USB devices on system:') out(pprint.pformat(devices)) + wmi = Wmi =None if iswindows: - if iswindows: - import pythoncom - pythoncom.CoInitialize() + wmi = __import__('wmi', globals(), locals(), [], -1) + Wmi = wmi.WMI(find_classes=False) + drives = [] + out('Drives detected:') + out('\t', '(ID, Partitions, Drive letter)') + for drive in Wmi.Win32_DiskDrive(): + if drive.Partitions == 0: + continue try: - wmi = __import__('wmi', globals(), locals(), [], -1) - drives = [] - out('Drives detected:') - out('\t', '(ID, Partitions, Drive letter)') - for drive in wmi.WMI(find_classes=False).Win32_DiskDrive(): - if drive.Partitions == 0: - continue - try: - partition = drive.associators("Win32_DiskDriveToDiskPartition")[0] - logical_disk = partition.associators('Win32_LogicalDiskToPartition')[0] - prefix = logical_disk.DeviceID+os.sep - drives.append((str(drive.PNPDeviceID), drive.Index, prefix)) - except IndexError: - drives.append((str(drive.PNPDeviceID), 'No mount points found')) - for drive in drives: - out('\t', drive) - finally: - pythoncom.CoUninitialize() + partition = drive.associators("Win32_DiskDriveToDiskPartition")[0] + logical_disk = partition.associators('Win32_LogicalDiskToPartition')[0] + prefix = logical_disk.DeviceID+os.sep + drives.append((str(drive.PNPDeviceID), drive.Index, prefix)) + except IndexError: + drives.append((str(drive.PNPDeviceID), 'No mount points found')) + for drive in drives: + out('\t', drive) ioreg = None if isosx: @@ -81,17 +81,26 @@ def debug(ioreg_to_tmp=False, buf=None): ioreg = Device.run_ioreg() ioreg = 'Output from mount:\n\n'+mount+'\n\n'+ioreg connected_devices = [] + s.wmi = Wmi for dev in device_plugins(): + owmi = getattr(dev, 'wmi', None) + dev.wmi = Wmi out('Looking for', dev.__class__.__name__) connected, det = s.is_device_connected(dev, debug=True) if connected: connected_devices.append((dev, det)) + dev.wmi = owmi errors = {} success = False + out('Devices possibly connected:', end=' ') for dev, det in connected_devices: - out('Device possibly connected:', dev.__class__.name) - out('Trying to open device...', end=' ') + out(dev.name, end=', ') + out(' ') + for dev, det in connected_devices: + out('Trying to open', dev.name, '...', end=' ') + owmi = getattr(dev, 'wmi', None) + dev.wmi = Wmi try: dev.reset(detected_device=det) dev.open() @@ -101,6 +110,8 @@ def debug(ioreg_to_tmp=False, buf=None): errors[dev] = traceback.format_exc() out('failed') continue + finally: + dev.wmi = owmi success = True if hasattr(dev, '_main_prefix'): out('Main memory:', repr(dev._main_prefix)) @@ -128,4 +139,7 @@ def debug(ioreg_to_tmp=False, buf=None): finally: sys.stdout = oldo sys.stderr = olde + if iswindows: + import pythoncom + pythoncom.CoUninitialize() diff --git a/src/calibre/devices/interface.py b/src/calibre/devices/interface.py index dec3f0304a..128a0bf45e 100644 --- a/src/calibre/devices/interface.py +++ b/src/calibre/devices/interface.py @@ -43,8 +43,7 @@ class DevicePlugin(Plugin): #: Icon for this device icon = I('reader.svg') - @classmethod - def test_bcd_windows(cls, device_id, bcd): + def test_bcd_windows(self, device_id, bcd): if bcd is None or len(bcd) == 0: return True for c in bcd: @@ -54,30 +53,28 @@ class DevicePlugin(Plugin): return True return False - @classmethod - def print_usb_device_info(cls, info): + def print_usb_device_info(self, info): try: print '\t', repr(info) except: import traceback traceback.print_exc() - @classmethod - def is_usb_connected_windows(cls, devices_on_system, debug=False): + def is_usb_connected_windows(self, devices_on_system, pnp_id_iterator, debug=False): def id_iterator(): - if hasattr(cls.VENDOR_ID, 'keys'): - for vid in cls.VENDOR_ID: - vend = cls.VENDOR_ID[vid] + if hasattr(self.VENDOR_ID, 'keys'): + for vid in self.VENDOR_ID: + vend = self.VENDOR_ID[vid] for pid in vend: bcd = vend[pid] yield vid, pid, bcd else: - vendors = cls.VENDOR_ID if hasattr(cls.VENDOR_ID, '__len__') else [cls.VENDOR_ID] - products = cls.PRODUCT_ID if hasattr(cls.PRODUCT_ID, '__len__') else [cls.PRODUCT_ID] + vendors = self.VENDOR_ID if hasattr(self.VENDOR_ID, '__len__') else [self.VENDOR_ID] + products = self.PRODUCT_ID if hasattr(self.PRODUCT_ID, '__len__') else [self.PRODUCT_ID] for vid in vendors: for pid in products: - yield vid, pid, cls.BCD + yield vid, pid, self.BCD for vendor_id, product_id, bcd in id_iterator(): vid, pid = 'vid_%4.4x'%vendor_id, 'pid_%4.4x'%product_id @@ -85,15 +82,14 @@ class DevicePlugin(Plugin): for device_id in devices_on_system: if (vid in device_id or vidd in device_id) and \ (pid in device_id or pidd in device_id) and \ - cls.test_bcd_windows(device_id, bcd): + self.test_bcd_windows(device_id, bcd): if debug: - cls.print_usb_device_info(device_id) - if cls.can_handle(device_id): + self.print_usb_device_info(device_id) + if self.can_handle_windows(device_id, pnp_id_iterator, debug=debug): return True return False - @classmethod - def test_bcd(cls, bcdDevice, bcd): + def test_bcd(self, bcdDevice, bcd): if bcd is None or len(bcd) == 0: return True for c in bcd: @@ -101,24 +97,24 @@ class DevicePlugin(Plugin): return True return False - @classmethod - def is_usb_connected(cls, devices_on_system, debug=False): + def is_usb_connected(self, devices_on_system, pnp_id_iterator, debug=False): ''' Return True, device_info if a device handled by this plugin is currently connected. :param devices_on_system: List of devices currently connected ''' if iswindows: - return cls.is_usb_connected_windows(devices_on_system, debug=debug), None + return self.is_usb_connected_windows(devices_on_system, + pnp_id_iterator, debug=debug), None vendors_on_system = set([x[0] for x in devices_on_system]) - vendors = cls.VENDOR_ID if hasattr(cls.VENDOR_ID, '__len__') else [cls.VENDOR_ID] - if hasattr(cls.VENDOR_ID, 'keys'): + vendors = self.VENDOR_ID if hasattr(self.VENDOR_ID, '__len__') else [self.VENDOR_ID] + if hasattr(self.VENDOR_ID, 'keys'): products = [] - for ven in cls.VENDOR_ID: - products.extend(cls.VENDOR_ID[ven].keys()) + for ven in self.VENDOR_ID: + products.extend(self.VENDOR_ID[ven].keys()) else: - products = cls.PRODUCT_ID if hasattr(cls.PRODUCT_ID, '__len__') else [cls.PRODUCT_ID] + products = self.PRODUCT_ID if hasattr(self.PRODUCT_ID, '__len__') else [self.PRODUCT_ID] for vid in vendors: if vid in vendors_on_system: @@ -126,14 +122,14 @@ class DevicePlugin(Plugin): cvid, pid, bcd = dev[:3] if cvid == vid: if pid in products: - if hasattr(cls.VENDOR_ID, 'keys'): - cbcd = cls.VENDOR_ID[vid][pid] + if hasattr(self.VENDOR_ID, 'keys'): + cbcd = self.VENDOR_ID[vid][pid] else: - cbcd = cls.BCD - if cls.test_bcd(bcd, cbcd): + cbcd = self.BCD + if self.test_bcd(bcd, cbcd): if debug: - cls.print_usb_device_info(dev) - if cls.can_handle(dev, debug=debug): + self.print_usb_device_info(dev) + if self.can_handle(dev, debug=debug): return True, dev return False, None @@ -151,25 +147,30 @@ class DevicePlugin(Plugin): """ raise NotImplementedError() - @classmethod - def get_fdi(cls): - '''Return the FDI description of this device for HAL on linux.''' - return '' - - @classmethod - def can_handle(cls, device_info, debug=False): + def can_handle_windows(self, device_id, pnp_id_iterator, debug=False): ''' Optional method to perform further checks on a device to see if this driver is capable of handling it. If it is not it should return False. This method is only called after the vendor, product ids and the bcd have matched, so it can do some relatively time intensive checks. The default implementation - returns True. + returns True. This method is called only on windows. See also + :method:`can_handle`. :param device_info: On windows a device ID string. On Unix a tuple of ``(vendor_id, product_id, bcd)``. ''' return True + def can_handle(self, device_info, debug=False): + ''' + Unix version of :method:`can_handle_windows` + + :param device_info: Is a tupe of (vid, pid, bcd, manufacturer, product, + serial number) + ''' + + return True + def open(self): ''' Perform any device specific initialization. Called after the device is diff --git a/src/calibre/devices/prs500/cli/main.py b/src/calibre/devices/prs500/cli/main.py index a49bca4794..2b942d4cfc 100755 --- a/src/calibre/devices/prs500/cli/main.py +++ b/src/calibre/devices/prs500/cli/main.py @@ -197,15 +197,15 @@ def main(): command = args[0] args = args[1:] dev = None - _wmi = None + scanner = DeviceScanner() if iswindows: import wmi, pythoncom pythoncom.CoInitialize() - _wmi = wmi.WMI() - scanner = DeviceScanner(_wmi) + scanner.wmi = wmi.WMI(find_classes=False) scanner.scan() connected_devices = [] for d in device_plugins(): + d.wmi = scanner.wmi ok, det = scanner.is_device_connected(d) if ok: dev = d diff --git a/src/calibre/devices/scanner.py b/src/calibre/devices/scanner.py index ef83659fe3..839552e9a7 100644 --- a/src/calibre/devices/scanner.py +++ b/src/calibre/devices/scanner.py @@ -85,13 +85,26 @@ class DeviceScanner(object): raise RuntimeError('DeviceScanner requires the /sys filesystem to work.') self.scanner = win_scanner if iswindows else osx_scanner if isosx else linux_scanner self.devices = [] + self.wmi = None + self.pnp_ids = set([]) + self.rescan_pnp_ids = True def scan(self): '''Fetch list of connected USB devices from operating system''' self.devices = self.scanner() + if self.rescan_pnp_ids: + self.pnp_ids = set([]) + + def pnp_id_iterator(self): + if self.wmi is not None and not self.pnp_ids: + for drive in self.wmi.Win32_DiskDrive(): + if drive.Partitions > 0: + self.pnp_ids.add(str(drive.PNPDeviceID)) + for x in self.pnp_ids: + yield x def is_device_connected(self, device, debug=False): - return device.is_usb_connected(self.devices, debug=debug) + return device.is_usb_connected(self.devices, self.pnp_id_iterator, debug=debug) def main(args=sys.argv): diff --git a/src/calibre/devices/usbms/device.py b/src/calibre/devices/usbms/device.py index 5d09d3821f..88f7cb3f19 100644 --- a/src/calibre/devices/usbms/device.py +++ b/src/calibre/devices/usbms/device.py @@ -22,7 +22,7 @@ from itertools import repeat from calibre.devices.interface import DevicePlugin from calibre.devices.errors import DeviceError, FreeSpaceError from calibre.devices.usbms.deviceconfig import DeviceConfig -from calibre.constants import iswindows, islinux, isosx, __appname__, plugins +from calibre.constants import iswindows, islinux, isosx, plugins from calibre.utils.filenames import ascii_filename as sanitize, shorten_components_to if isosx: @@ -83,53 +83,6 @@ class Device(DeviceConfig, DevicePlugin): EBOOK_DIR_CARD_B = '' DELETE_EXTS = [] - FDI_TEMPLATE = \ -''' - - - - - %(BCD_start)s - - %(main_memory)s - %(deviceclass)s - - %(BCD_end)s - - - - - - - - - %(BCD_start)s - - %(storage_card)s - %(deviceclass)s - - %(BCD_end)s - - - - - - - - - %(BCD_start)s - - %(storage_card)s - %(deviceclass)s - - %(BCD_end)s - - - - -''' - FDI_LUNS = {'lun0':0, 'lun1':1, 'lun2':2} - FDI_BCD_TEMPLATE = '' def reset(self, key='-1', log_packets=False, report_progress=None, detected_device=None): @@ -138,6 +91,7 @@ class Device(DeviceConfig, DevicePlugin): self.detected_device = USBDevice(detected_device) except: # On windows detected_device is None self.detected_device = None + self.set_progress_reporter(report_progress) @classmethod def get_gui_name(cls): @@ -146,37 +100,11 @@ class Device(DeviceConfig, DevicePlugin): x = cls.__name__ return x - - @classmethod - def get_fdi(cls): - fdi = '' - for vid in cls.VENDOR_ID: - for pid in cls.PRODUCT_ID: - fdi_base_values = dict( - app=__appname__, - deviceclass=cls.__name__, - vendor_id=hex(vid), - product_id=hex(pid), - main_memory=cls.MAIN_MEMORY_VOLUME_LABEL, - storage_card=cls.STORAGE_CARD_VOLUME_LABEL, - ) - fdi_base_values.update(cls.FDI_LUNS) - - if cls.BCD is None: - fdi_base_values['BCD_start'] = '' - fdi_base_values['BCD_end'] = '' - fdi += cls.FDI_TEMPLATE % fdi_base_values - else: - for bcd in cls.BCD: - fdi_bcd_values = fdi_base_values - fdi_bcd_values['BCD_start'] = cls.FDI_BCD_TEMPLATE % dict(bcd=hex(bcd)) - fdi_bcd_values['BCD_end'] = '' - fdi += cls.FDI_TEMPLATE % fdi_bcd_values - - return fdi - def set_progress_reporter(self, report_progress): self.report_progress = report_progress + self.report_progress = report_progress + if self.report_progress is None: + self.report_progress = lambda x, y: x def card_prefix(self, end_session=True): return (self._card_a_prefix, self._card_b_prefix) @@ -239,9 +167,7 @@ class Device(DeviceConfig, DevicePlugin): def windows_filter_pnp_id(self, pnp_id): return False - def windows_match_device(self, drive, attr): - pnp_id = (str(drive.PNPDeviceID) if not isinstance(drive, basestring) - else str(drive)).upper() + def windows_match_device(self, pnp_id, attr): device_id = getattr(self, attr) def test_vendor(): @@ -292,6 +218,12 @@ class Device(DeviceConfig, DevicePlugin): ''' return drives + def can_handle_windows(self, device_id, pnp_id_iterator, debug=False): + for pnp_id in pnp_id_iterator(): + if self.windows_match_device(pnp_id, 'WINDOWS_MAIN_MEM'): + return True + return False + def open_windows(self): def matches_q(drive, attr): @@ -307,14 +239,14 @@ class Device(DeviceConfig, DevicePlugin): time.sleep(8) drives = {} - wmi = __import__('wmi', globals(), locals(), [], -1) - c = wmi.WMI(find_classes=False) + c = self.wmi for drive in c.Win32_DiskDrive(): - if self.windows_match_device(drive, 'WINDOWS_CARD_A_MEM') and not drives.get('carda', None): + pnp_id = str(drive.PNPDeviceID) + if self.windows_match_device(pnp_id, 'WINDOWS_CARD_A_MEM') and not drives.get('carda', None): drives['carda'] = self.windows_get_drive_prefix(drive) - elif self.windows_match_device(drive, 'WINDOWS_CARD_B_MEM') and not drives.get('cardb', None): + elif self.windows_match_device(pnp_id, 'WINDOWS_CARD_B_MEM') and not drives.get('cardb', None): drives['cardb'] = self.windows_get_drive_prefix(drive) - elif self.windows_match_device(drive, 'WINDOWS_MAIN_MEM') and not drives.get('main', None): + elif self.windows_match_device(pnp_id, 'WINDOWS_MAIN_MEM') and not drives.get('main', None): drives['main'] = self.windows_get_drive_prefix(drive) if 'main' in drives.keys() and 'carda' in drives.keys() and \ diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index ec91e70257..d302c10d09 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -72,15 +72,12 @@ class DeviceManager(Thread): def __init__(self, connected_slot, job_manager, sleep_time=2): ''' - @param sleep_time: Time to sleep between device probes in secs - @type sleep_time: integer + :sleep_time: Time to sleep between device probes in secs ''' Thread.__init__(self) self.setDaemon(True) # [Device driver, Showing in GUI, Ejected] - self.devices = [[d, False, False] for d in device_plugins()] - self.device = None - self.device_class = None + self.devices = list(device_plugins()) self.sleep_time = sleep_time self.connected_slot = connected_slot self.jobs = Queue.Queue(0) @@ -88,75 +85,83 @@ class DeviceManager(Thread): self.job_manager = job_manager self.current_job = None self.scanner = DeviceScanner() + self.wmi = None + self.connected_device = None + self.ejected_devices = set([]) + + def report_progress(self, *args): + pass + + @property + def is_device_connected(self): + return self.connected_device is not None + + @property + def device(self): + return self.connected_device def do_connect(self, connected_devices): - if iswindows: - import pythoncom - pythoncom.CoInitialize() - try: - for dev, detected_device in connected_devices: - dev.reset(detected_device=detected_device) - try: - dev.open() - except: - print 'Unable to open device', dev - traceback.print_exc() - continue - self.device = dev - self.device_class = dev.__class__ - self.connected_slot(True) - return True - finally: - if iswindows: - pythoncom.CoUninitialize() + for dev, detected_device in connected_devices: + dev.reset(detected_device=detected_device, + report_progress=self.report_progress) + try: + dev.open() + except: + print 'Unable to open device', dev + traceback.print_exc() + continue + self.connected_device = dev + self.connected_slot(True) + return True return False + def connected_device_removed(self): + while True: + try: + job = self.jobs.get_nowait() + job.abort(Exception(_('Device no longer connected.'))) + except Queue.Empty: + break + try: + self.connected_device.post_yank_cleanup() + except: + pass + if self.connected_device in self.ejected_devices: + self.ejected_devices.remove(self.connected_device) + else: + self.connected_slot(False) + self.connected_device = None def detect_device(self): + self.scanner.rescan_pnp_ids = not self.is_device_connected self.scanner.scan() - connected_devices = [] - for device in self.devices: - connected, detected_device = self.scanner.is_device_connected(device[0]) - if connected and not device[1] and not device[2]: - # If connected and not showing in GUI and not ejected - connected_devices.append((device[0], detected_device)) - device[1] = True - elif not connected and device[1]: - # Disconnected but showing in GUI - while True: - try: - job = self.jobs.get_nowait() - job.abort(Exception(_('Device no longer connected.'))) - except Queue.Empty: - break - try: - self.device.post_yank_cleanup() - except: - pass - device[2] = False - self.device = None - self.connected_slot(False) - device[1] ^= True - if connected_devices: - if not self.do_connect(connected_devices): - print 'Connect to device failed, retying in 5 seconds...' - time.sleep(5) - if not self.do_connect(connected_devices): - print 'Device connect failed again, giving up' + if self.is_device_connected: + connected, detected_device = \ + self.scanner.is_device_connected(self.connected_device) + if not connected: + self.connected_device_removed() + else: + possibly_connected_devices = [] + for device in self.devices: + if device in self.ejected_devices: + continue + possibly_connected, detected_device = \ + self.scanner.is_device_connected(device) + if possibly_connected: + possibly_connected_devices.append((device, detected_device)) + if possibly_connected_devices: + if not self.do_connect(possibly_connected_devices): + print 'Connect to device failed, retying in 5 seconds...' + time.sleep(5) + if not self.do_connect(possibly_connected_devices): + print 'Device connect failed again, giving up' def umount_device(self): - if self.device is not None: - self.device.eject() - dev = None - for x in self.devices: - if x[0] is self.device: - dev = x - break - if dev is not None: - dev[2] = True + if self.is_device_connected: + self.connected_device.eject() + self.ejected_devices.add(self.connected_device) self.connected_slot(False) - def next(self): if not self.jobs.empty(): try: @@ -165,18 +170,31 @@ class DeviceManager(Thread): pass def run(self): - while self.keep_going: - self.detect_device() - while True: - job = self.next() - if job is not None: - self.current_job = job - self.device.set_progress_reporter(job.report_progress) - self.current_job.run() - self.current_job = None - else: - break - time.sleep(self.sleep_time) + if iswindows: + import pythoncom + pythoncom.CoInitialize() + wmi = __import__('wmi', globals(), locals(), [], -1) + self.wmi = wmi.WMI(find_classes=False) + self.scanner.wmi = self.wmi + for x in self.devices: + x[0].wmi = self.wmi + try: + while self.keep_going: + self.detect_device() + while True: + job = self.next() + if job is not None: + self.current_job = job + self.device.set_progress_reporter(job.report_progress) + self.current_job.run() + self.current_job = None + else: + break + time.sleep(self.sleep_time) + finally: + if iswindows: + pythoncom.CoUninitialize() + def create_job(self, func, done, description, args=[], kwargs={}): job = DeviceJob(func, done, self.job_manager, @@ -495,7 +513,7 @@ class DeviceGUI(object): fmt = None if specific: d = ChooseFormatDialog(self, _('Choose format to send to device'), - self.device_manager.device_class.settings().format_map) + self.device_manager.device.settings().format_map) d.exec_() fmt = d.format().lower() dest, sub_dest = dest.split(':') @@ -637,7 +655,7 @@ class DeviceGUI(object): p = QPixmap() p.loadFromData(data) if not p.isNull(): - ht = self.device_manager.device_class.THUMBNAIL_HEIGHT \ + ht = self.device_manager.device.THUMBNAIL_HEIGHT \ if self.device_manager else DevicePlugin.THUMBNAIL_HEIGHT p = p.scaledToHeight(ht, Qt.SmoothTransformation) return (p.width(), p.height(), pixmap_to_data(p)) @@ -675,10 +693,11 @@ class DeviceGUI(object): def sync_news(self, send_ids=None, do_auto_convert=True): if self.device_connected: + settings = self.device_manager.device.settings() ids = list(dynamic.get('news_to_be_synced', set([]))) if send_ids is None else send_ids ids = [id for id in ids if self.library_view.model().db.has_id(id)] files, _auto_ids = self.library_view.model().get_preferred_formats_from_ids( - ids, self.device_manager.device_class.settings().format_map, + ids, settings.format_map, exclude_auto=do_auto_convert) auto = [] if do_auto_convert and _auto_ids: @@ -687,12 +706,12 @@ class DeviceGUI(object): formats = [] if dbfmts is None else \ [f.lower() for f in dbfmts.split(',')] if set(formats).intersection(available_input_formats()) \ - and set(self.device_manager.device_class.settings().format_map).intersection(available_output_formats()): + and set(settings.format_map).intersection(available_output_formats()): auto.append(id) if auto: format = None - for fmt in self.device_manager.device_class.settings().format_map: - if fmt in list(set(self.device_manager.device_class.settings().format_map).intersection(set(available_output_formats()))): + for fmt in settings.format_map: + if fmt in list(set(settings.format_map).intersection(set(available_output_formats()))): format = fmt break if format is not None: @@ -738,8 +757,10 @@ class DeviceGUI(object): if not self.device_manager or not ids or len(ids) == 0: return + settings = self.device_manager.device.settings() + _files, _auto_ids = self.library_view.model().get_preferred_formats_from_ids(ids, - self.device_manager.device_class.settings().format_map, + settings.format_map, paths=True, set_metadata=True, specific_format=specific_format, exclude_auto=do_auto_convert) @@ -790,21 +811,21 @@ class DeviceGUI(object): formats = self.library_view.model().db.formats(id, index_is_id=True) formats = formats.split(',') if formats is not None else [] formats = [f.lower().strip() for f in formats] - if list(set(formats).intersection(available_input_formats())) != [] and list(set(self.device_manager.device_class.settings().format_map).intersection(available_output_formats())) != []: + if list(set(formats).intersection(available_input_formats())) != [] and list(set(settings.format_map).intersection(available_output_formats())) != []: auto.append(id) else: bad.append(self.library_view.model().db.title(id, index_is_id=True)) else: - if specific_format in list(set(self.device_manager.device_class.settings().format_map).intersection(set(available_output_formats()))): + if specific_format in list(set(settings.format_map).intersection(set(available_output_formats()))): auto.append(id) else: bad.append(self.library_view.model().db.title(id, index_is_id=True)) if auto != []: - format = specific_format if specific_format in list(set(self.device_manager.device_class.settings().format_map).intersection(set(available_output_formats()))) else None + format = specific_format if specific_format in list(set(settings.format_map).intersection(set(available_output_formats()))) else None if not format: - for fmt in self.device_manager.device_class.settings().format_map: - if fmt in list(set(self.device_manager.device_class.settings().format_map).intersection(set(available_output_formats()))): + for fmt in settings.format_map: + if fmt in list(set(settings.format_map).intersection(set(available_output_formats()))): format = fmt break if not format: diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index f9fbcbae3a..c90a70f4d3 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -840,11 +840,11 @@ class Main(MainWindow, Ui_MainWindow, DeviceGUI): return mainlist, cardalist, cardblist = job.result self.memory_view.set_database(mainlist) - self.memory_view.set_editable(self.device_manager.device_class.CAN_SET_METADATA) + self.memory_view.set_editable(self.device_manager.device.CAN_SET_METADATA) self.card_a_view.set_database(cardalist) - self.card_a_view.set_editable(self.device_manager.device_class.CAN_SET_METADATA) + self.card_a_view.set_editable(self.device_manager.device.CAN_SET_METADATA) self.card_b_view.set_database(cardblist) - self.card_b_view.set_editable(self.device_manager.device_class.CAN_SET_METADATA) + self.card_b_view.set_editable(self.device_manager.device.CAN_SET_METADATA) for view in (self.memory_view, self.card_a_view, self.card_b_view): view.sortByColumn(3, Qt.DescendingOrder) view.read_settings()