diff --git a/src/calibre/devices/interface.py b/src/calibre/devices/interface.py index 2b3bbd4fd6..9b173b091e 100644 --- a/src/calibre/devices/interface.py +++ b/src/calibre/devices/interface.py @@ -107,6 +107,12 @@ class DevicePlugin(Plugin): #: :meth:`set_user_blacklisted_devices` ASK_TO_ALLOW_CONNECT = False + #: Set this to a dictionary of the form {'title':title, 'msg':msg, 'det_msg':detailed_msg} to have calibre popup + #: a message to the user after some callbacks are run (currently only upload_books). + #: Be careful to not spam the user with too many messages. This variable is checked after *every* callback, + #: so only set it when you really need to. + user_feedback_after_callback = None + @classmethod def get_gui_name(cls): if hasattr(cls, 'gui_name'): @@ -157,16 +163,15 @@ class DevicePlugin(Plugin): if (vid in device_id or vidd in device_id) and \ (pid in device_id or pidd in device_id) and \ self.test_bcd_windows(device_id, bcd): - if debug: - self.print_usb_device_info(device_id) - if only_presence or self.can_handle_windows(device_id, debug=debug): - try: - bcd = int(device_id.rpartition( - 'rev_')[-1].replace(':', 'a'), 16) - except: - bcd = None - return True, (vendor_id, product_id, bcd, None, - None, None) + if debug: + self.print_usb_device_info(device_id) + if only_presence or self.can_handle_windows(device_id, debug=debug): + try: + bcd = int(device_id.rpartition( + 'rev_')[-1].replace(':', 'a'), 16) + except: + bcd = None + return True, (vendor_id, product_id, bcd, None, None, None) return False, None def test_bcd(self, bcdDevice, bcd): @@ -638,7 +643,6 @@ class DevicePlugin(Plugin): ''' device_prefs.set_overrides() - # Dynamic control interface. # The following methods are probably called on the GUI thread. Any driver # that implements these methods must take pains to be thread safe, because diff --git a/src/calibre/gui2/device.py b/src/calibre/gui2/device.py index 45778ec309..15dc1f0c0a 100644 --- a/src/calibre/gui2/device.py +++ b/src/calibre/gui2/device.py @@ -122,7 +122,8 @@ def device_name_for_plugboards(device_class): class DeviceManager(Thread): # {{{ def __init__(self, connected_slot, job_manager, open_feedback_slot, - open_feedback_msg, allow_connect_slot, sleep_time=2): + open_feedback_msg, allow_connect_slot, + after_callback_feedback_slot, sleep_time=2): ''' :sleep_time: Time to sleep between device probes in secs ''' @@ -150,6 +151,7 @@ class DeviceManager(Thread): # {{{ self.ejected_devices = set([]) self.mount_connection_requests = Queue.Queue(0) self.open_feedback_slot = open_feedback_slot + self.after_callback_feedback_slot = after_callback_feedback_slot self.open_feedback_msg = open_feedback_msg self._device_information = None self.current_library_uuid = None @@ -392,6 +394,10 @@ class DeviceManager(Thread): # {{{ self.device.set_progress_reporter(job.report_progress) self.current_job.run() self.current_job = None + feedback = getattr(self.device, 'user_feedback_after_callback', None) + if feedback is not None: + self.device.user_feedback_after_callback = None + self.after_callback_feedback_slot(feedback) else: break if do_sleep: @@ -850,7 +856,7 @@ class DeviceMixin(object): # {{{ self.device_manager = DeviceManager(FunctionDispatcher(self.device_detected), self.job_manager, Dispatcher(self.status_bar.show_message), Dispatcher(self.show_open_feedback), - FunctionDispatcher(self.allow_connect)) + FunctionDispatcher(self.allow_connect), Dispatcher(self.after_callback_feedback)) self.device_manager.start() self.device_manager.devices_initialized.wait() if tweaks['auto_connect_to_folder']: @@ -862,6 +868,10 @@ class DeviceMixin(object): # {{{ name, show_copy_button=False, override_icon=QIcon(icon)) + def after_callback_feedback(self, feedback): + title, msg, det_msg = feedback + info_dialog(self, feedback['title'], feedback['msg'], det_msg=feedback['det_msg']).show() + def debug_detection(self, done): self.debug_detection_callback = weakref.ref(done) self.device_manager.debug_detection(FunctionDispatcher(self.debug_detection_done)) @@ -1116,7 +1126,7 @@ class DeviceMixin(object): # {{{ return dm = self.iactions['Remove Books'].delete_memory - if dm.has_key(job): + if job in dm: paths, model = dm.pop(job) self.device_manager.remove_books_from_metadata(paths, self.booklists()) @@ -1141,7 +1151,7 @@ class DeviceMixin(object): # {{{ def dispatch_sync_event(self, dest, delete, specific): rows = self.library_view.selectionModel().selectedRows() if not rows or len(rows) == 0: - error_dialog(self, _('No books'), _('No books')+' '+\ + error_dialog(self, _('No books'), _('No books')+' '+ _('selected to send')).exec_() return @@ -1160,7 +1170,7 @@ class DeviceMixin(object): # {{{ if fmts: for f in fmts.split(','): f = f.lower() - if format_count.has_key(f): + if f in format_count: format_count[f] += 1 else: format_count[f] = 1