Add mechanism for device drivers to popup a message to the user after a callback

This commit is contained in:
Kovid Goyal 2013-05-13 21:46:48 +05:30
parent ed422c7b0f
commit e637b32485
2 changed files with 30 additions and 16 deletions

View File

@ -107,6 +107,12 @@ class DevicePlugin(Plugin):
#: :meth:`set_user_blacklisted_devices` #: :meth:`set_user_blacklisted_devices`
ASK_TO_ALLOW_CONNECT = False 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 @classmethod
def get_gui_name(cls): def get_gui_name(cls):
if hasattr(cls, 'gui_name'): if hasattr(cls, 'gui_name'):
@ -157,16 +163,15 @@ class DevicePlugin(Plugin):
if (vid in device_id or vidd in device_id) and \ if (vid in device_id or vidd in device_id) and \
(pid in device_id or pidd in device_id) and \ (pid in device_id or pidd in device_id) and \
self.test_bcd_windows(device_id, bcd): self.test_bcd_windows(device_id, bcd):
if debug: if debug:
self.print_usb_device_info(device_id) self.print_usb_device_info(device_id)
if only_presence or self.can_handle_windows(device_id, debug=debug): if only_presence or self.can_handle_windows(device_id, debug=debug):
try: try:
bcd = int(device_id.rpartition( bcd = int(device_id.rpartition(
'rev_')[-1].replace(':', 'a'), 16) 'rev_')[-1].replace(':', 'a'), 16)
except: except:
bcd = None bcd = None
return True, (vendor_id, product_id, bcd, None, return True, (vendor_id, product_id, bcd, None, None, None)
None, None)
return False, None return False, None
def test_bcd(self, bcdDevice, bcd): def test_bcd(self, bcdDevice, bcd):
@ -638,7 +643,6 @@ class DevicePlugin(Plugin):
''' '''
device_prefs.set_overrides() device_prefs.set_overrides()
# Dynamic control interface. # Dynamic control interface.
# The following methods are probably called on the GUI thread. Any driver # The following methods are probably called on the GUI thread. Any driver
# that implements these methods must take pains to be thread safe, because # that implements these methods must take pains to be thread safe, because

View File

@ -122,7 +122,8 @@ def device_name_for_plugboards(device_class):
class DeviceManager(Thread): # {{{ class DeviceManager(Thread): # {{{
def __init__(self, connected_slot, job_manager, open_feedback_slot, 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 :sleep_time: Time to sleep between device probes in secs
''' '''
@ -150,6 +151,7 @@ class DeviceManager(Thread): # {{{
self.ejected_devices = set([]) self.ejected_devices = set([])
self.mount_connection_requests = Queue.Queue(0) self.mount_connection_requests = Queue.Queue(0)
self.open_feedback_slot = open_feedback_slot self.open_feedback_slot = open_feedback_slot
self.after_callback_feedback_slot = after_callback_feedback_slot
self.open_feedback_msg = open_feedback_msg self.open_feedback_msg = open_feedback_msg
self._device_information = None self._device_information = None
self.current_library_uuid = None self.current_library_uuid = None
@ -392,6 +394,10 @@ class DeviceManager(Thread): # {{{
self.device.set_progress_reporter(job.report_progress) self.device.set_progress_reporter(job.report_progress)
self.current_job.run() self.current_job.run()
self.current_job = None 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: else:
break break
if do_sleep: if do_sleep:
@ -850,7 +856,7 @@ class DeviceMixin(object): # {{{
self.device_manager = DeviceManager(FunctionDispatcher(self.device_detected), self.device_manager = DeviceManager(FunctionDispatcher(self.device_detected),
self.job_manager, Dispatcher(self.status_bar.show_message), self.job_manager, Dispatcher(self.status_bar.show_message),
Dispatcher(self.show_open_feedback), 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.start()
self.device_manager.devices_initialized.wait() self.device_manager.devices_initialized.wait()
if tweaks['auto_connect_to_folder']: if tweaks['auto_connect_to_folder']:
@ -862,6 +868,10 @@ class DeviceMixin(object): # {{{
name, show_copy_button=False, name, show_copy_button=False,
override_icon=QIcon(icon)) 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): def debug_detection(self, done):
self.debug_detection_callback = weakref.ref(done) self.debug_detection_callback = weakref.ref(done)
self.device_manager.debug_detection(FunctionDispatcher(self.debug_detection_done)) self.device_manager.debug_detection(FunctionDispatcher(self.debug_detection_done))
@ -1116,7 +1126,7 @@ class DeviceMixin(object): # {{{
return return
dm = self.iactions['Remove Books'].delete_memory dm = self.iactions['Remove Books'].delete_memory
if dm.has_key(job): if job in dm:
paths, model = dm.pop(job) paths, model = dm.pop(job)
self.device_manager.remove_books_from_metadata(paths, self.device_manager.remove_books_from_metadata(paths,
self.booklists()) self.booklists())
@ -1141,7 +1151,7 @@ class DeviceMixin(object): # {{{
def dispatch_sync_event(self, dest, delete, specific): def dispatch_sync_event(self, dest, delete, specific):
rows = self.library_view.selectionModel().selectedRows() rows = self.library_view.selectionModel().selectedRows()
if not rows or len(rows) == 0: 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_() _('selected to send')).exec_()
return return
@ -1160,7 +1170,7 @@ class DeviceMixin(object): # {{{
if fmts: if fmts:
for f in fmts.split(','): for f in fmts.split(','):
f = f.lower() f = f.lower()
if format_count.has_key(f): if f in format_count:
format_count[f] += 1 format_count[f] += 1
else: else:
format_count[f] = 1 format_count[f] = 1