mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Implement job step sequence priority
This commit is contained in:
parent
0876a3efd1
commit
d280eb8c29
@ -119,6 +119,7 @@ class DeviceManager(Thread): # {{{
|
||||
self.sleep_time = sleep_time
|
||||
self.connected_slot = connected_slot
|
||||
self.jobs = Queue.Queue(0)
|
||||
self.job_steps = Queue.Queue(0)
|
||||
self.keep_going = True
|
||||
self.job_manager = job_manager
|
||||
self.reported_errors = set([])
|
||||
@ -235,6 +236,12 @@ class DeviceManager(Thread): # {{{
|
||||
self.connected_device.unmount_device()
|
||||
|
||||
def next(self):
|
||||
if not self.job_steps.empty():
|
||||
try:
|
||||
return self.job_steps.get_nowait()
|
||||
except Queue.Empty:
|
||||
pass
|
||||
|
||||
if not self.jobs.empty():
|
||||
try:
|
||||
return self.jobs.get_nowait()
|
||||
@ -271,13 +278,23 @@ class DeviceManager(Thread): # {{{
|
||||
break
|
||||
time.sleep(self.sleep_time)
|
||||
|
||||
def create_job(self, func, done, description, args=[], kwargs={}):
|
||||
def create_job_step(self, func, done, description, to_job, args=[], kwargs={}):
|
||||
job = DeviceJob(func, done, self.job_manager,
|
||||
args=args, kwargs=kwargs, description=description)
|
||||
self.job_manager.add_job(job)
|
||||
if (done is None or isinstance(done, FunctionDispatcher)) and \
|
||||
(to_job is not None and to_job == self.current_job):
|
||||
print "adding as step", description
|
||||
self.job_steps.put(job)
|
||||
else:
|
||||
print "adding as job not step", description
|
||||
traceback.print_stack()
|
||||
self.jobs.put(job)
|
||||
return job
|
||||
|
||||
def create_job(self, func, done, description, args=[], kwargs={}):
|
||||
return self.create_job_step(func, done, description, None, args, kwargs)
|
||||
|
||||
def has_card(self):
|
||||
try:
|
||||
return bool(self.device.card_prefix())
|
||||
@ -295,10 +312,10 @@ class DeviceManager(Thread): # {{{
|
||||
self._device_information = {'info': info, 'prefixes': cp, 'freespace': fs}
|
||||
return info, cp, fs
|
||||
|
||||
def get_device_information(self, done):
|
||||
def get_device_information(self, done, add_as_step_to_job=None):
|
||||
'''Get device information and free space on device'''
|
||||
return self.create_job(self._get_device_information, done,
|
||||
description=_('Get device information'))
|
||||
return self.create_job_step(self._get_device_information, done,
|
||||
description=_('Get device information'), to_job=add_as_step_to_job)
|
||||
|
||||
def get_current_device_information(self):
|
||||
return self._device_information
|
||||
@ -310,36 +327,38 @@ class DeviceManager(Thread): # {{{
|
||||
cardblist = self.device.books(oncard='cardb')
|
||||
return (mainlist, cardalist, cardblist)
|
||||
|
||||
def books(self, done):
|
||||
def books(self, done, add_as_step_to_job=None):
|
||||
'''Return callable that returns the list of books on device as two booklists'''
|
||||
return self.create_job(self._books, done, description=_('Get list of books on device'))
|
||||
return self.create_job_step(self._books, done,
|
||||
description=_('Get list of books on device'), to_job=add_as_step_to_job)
|
||||
|
||||
def _annotations(self, path_map):
|
||||
return self.device.get_annotations(path_map)
|
||||
|
||||
def annotations(self, done, path_map):
|
||||
def annotations(self, done, path_map, add_as_step_to_job=None):
|
||||
'''Return mapping of ids to annotations. Each annotation is of the
|
||||
form (type, location_info, content). path_map is a mapping of
|
||||
ids to paths on the device.'''
|
||||
return self.create_job(self._annotations, done, args=[path_map],
|
||||
description=_('Get annotations from device'))
|
||||
return self.create_job_step(self._annotations, done, args=[path_map],
|
||||
description=_('Get annotations from device'), to_job=add_as_step_to_job)
|
||||
|
||||
def _sync_booklists(self, booklists):
|
||||
'''Sync metadata to device'''
|
||||
self.device.sync_booklists(booklists, end_session=False)
|
||||
return self.device.card_prefix(end_session=False), self.device.free_space()
|
||||
|
||||
def sync_booklists(self, done, booklists, plugboards):
|
||||
def sync_booklists(self, done, booklists, plugboards, add_as_step_to_job=None):
|
||||
if hasattr(self.connected_device, 'set_plugboards') and \
|
||||
callable(self.connected_device.set_plugboards):
|
||||
self.connected_device.set_plugboards(plugboards, find_plugboard)
|
||||
return self.create_job(self._sync_booklists, done, args=[booklists],
|
||||
description=_('Send metadata to device'))
|
||||
return self.create_job_step(self._sync_booklists, done, args=[booklists],
|
||||
description=_('Send metadata to device'), to_job=add_as_step_to_job)
|
||||
|
||||
def upload_collections(self, done, booklist, on_card):
|
||||
return self.create_job(booklist.rebuild_collections, done,
|
||||
def upload_collections(self, done, booklist, on_card, add_as_step_to_job=None):
|
||||
return self.create_job_step(booklist.rebuild_collections, done,
|
||||
args=[booklist, on_card],
|
||||
description=_('Send collections to device'))
|
||||
description=_('Send collections to device'),
|
||||
to_job=add_as_step_to_job)
|
||||
|
||||
def _upload_books(self, files, names, on_card=None, metadata=None, plugboards=None):
|
||||
'''Upload books to device: '''
|
||||
@ -374,11 +393,12 @@ class DeviceManager(Thread): # {{{
|
||||
metadata=metadata, end_session=False)
|
||||
|
||||
def upload_books(self, done, files, names, on_card=None, titles=None,
|
||||
metadata=None, plugboards=None):
|
||||
metadata=None, plugboards=None, add_as_step_to_job=None):
|
||||
desc = _('Upload %d books to device')%len(names)
|
||||
if titles:
|
||||
desc += u':' + u', '.join(titles)
|
||||
return self.create_job(self._upload_books, done, args=[files, names],
|
||||
return self.create_job_step(self._upload_books, done, to_job=add_as_step_to_job,
|
||||
args=[files, names],
|
||||
kwargs={'on_card':on_card,'metadata':metadata,'plugboards':plugboards}, description=desc)
|
||||
|
||||
def add_books_to_metadata(self, locations, metadata, booklists):
|
||||
@ -388,9 +408,10 @@ class DeviceManager(Thread): # {{{
|
||||
'''Remove books from device'''
|
||||
self.device.delete_books(paths, end_session=True)
|
||||
|
||||
def delete_books(self, done, paths):
|
||||
return self.create_job(self._delete_books, done, args=[paths],
|
||||
description=_('Delete books from device'))
|
||||
def delete_books(self, done, paths, add_as_step_to_job=None):
|
||||
return self.create_job_step(self._delete_books, done, args=[paths],
|
||||
description=_('Delete books from device'),
|
||||
to_job=add_as_step_to_job)
|
||||
|
||||
def remove_books_from_metadata(self, paths, booklists):
|
||||
self.device.remove_books_from_metadata(paths, booklists)
|
||||
@ -405,9 +426,10 @@ class DeviceManager(Thread): # {{{
|
||||
self.device.get_file(path, f)
|
||||
f.close()
|
||||
|
||||
def save_books(self, done, paths, target):
|
||||
return self.create_job(self._save_books, done, args=[paths, target],
|
||||
description=_('Download books from device'))
|
||||
def save_books(self, done, paths, target, add_as_step_to_job=None):
|
||||
return self.create_job_step(self._save_books, done, args=[paths, target],
|
||||
description=_('Download books from device'),
|
||||
to_job=add_as_step_to_job)
|
||||
|
||||
def _view_book(self, path, target):
|
||||
f = open(target, 'wb')
|
||||
@ -415,9 +437,9 @@ class DeviceManager(Thread): # {{{
|
||||
f.close()
|
||||
return target
|
||||
|
||||
def view_book(self, done, path, target):
|
||||
return self.create_job(self._view_book, done, args=[path, target],
|
||||
description=_('View book on device'))
|
||||
def view_book(self, done, path, target, add_as_step_to_job=None):
|
||||
return self.create_job_step(self._view_book, done, args=[path, target],
|
||||
description=_('View book on device'), to_job=add_as_step_to_job)
|
||||
|
||||
def set_current_library_uuid(self, uuid):
|
||||
self.current_library_uuid = uuid
|
||||
@ -778,7 +800,8 @@ class DeviceMixin(object): # {{{
|
||||
self.device_manager.device.icon)
|
||||
self.bars_manager.update_bars()
|
||||
self.status_bar.device_connected(info[0])
|
||||
self.device_manager.books(FunctionDispatcher(self.metadata_downloaded))
|
||||
self.device_manager.books(FunctionDispatcher(self.metadata_downloaded),
|
||||
add_as_step_to_job=job)
|
||||
|
||||
def metadata_downloaded(self, job):
|
||||
'''
|
||||
@ -788,7 +811,7 @@ class DeviceMixin(object): # {{{
|
||||
self.device_job_exception(job)
|
||||
return
|
||||
# set_books_in_library might schedule a sync_booklists job
|
||||
self.set_books_in_library(job.result, reset=True)
|
||||
self.set_books_in_library(job.result, reset=True, add_as_step_to_job=job)
|
||||
mainlist, cardalist, cardblist = job.result
|
||||
self.memory_view.set_database(mainlist)
|
||||
self.memory_view.set_editable(self.device_manager.device.CAN_SET_METADATA,
|
||||
@ -843,8 +866,8 @@ class DeviceMixin(object): # {{{
|
||||
# set_books_in_library even though books were not added because
|
||||
# the deleted book might have been an exact match. Upload the booklists
|
||||
# if set_books_in_library did not.
|
||||
if not self.set_books_in_library(self.booklists(), reset=True):
|
||||
self.upload_booklists()
|
||||
if not self.set_books_in_library(self.booklists(), reset=True, add_as_step_to_job=job):
|
||||
self.upload_booklists(job)
|
||||
self.book_on_device(None, reset=True)
|
||||
# We need to reset the ondevice flags in the library. Use a big hammer,
|
||||
# so we don't need to worry about whether some succeeded or not.
|
||||
@ -1193,13 +1216,14 @@ class DeviceMixin(object): # {{{
|
||||
self.device_manager.sync_booklists(Dispatcher(lambda x: x),
|
||||
self.booklists(), plugboards)
|
||||
|
||||
def upload_booklists(self):
|
||||
def upload_booklists(self, add_as_step_to_job=None):
|
||||
'''
|
||||
Upload metadata to device.
|
||||
'''
|
||||
plugboards = self.library_view.model().db.prefs.get('plugboards', {})
|
||||
self.device_manager.sync_booklists(FunctionDispatcher(self.metadata_synced),
|
||||
self.booklists(), plugboards)
|
||||
self.booklists(), plugboards,
|
||||
add_as_step_to_job=add_as_step_to_job)
|
||||
|
||||
def metadata_synced(self, job):
|
||||
'''
|
||||
@ -1274,8 +1298,8 @@ class DeviceMixin(object): # {{{
|
||||
# because the UUID changed. Force both the device and the library view
|
||||
# to refresh the flags. Set_books_in_library could upload the booklists.
|
||||
# If it does not, then do it here.
|
||||
if not self.set_books_in_library(self.booklists(), reset=True):
|
||||
self.upload_booklists()
|
||||
if not self.set_books_in_library(self.booklists(), reset=True, add_as_step_to_job=job):
|
||||
self.upload_booklists(job)
|
||||
with self.library_view.preserve_selected_books:
|
||||
self.book_on_device(None, reset=True)
|
||||
self.refresh_ondevice()
|
||||
@ -1335,7 +1359,7 @@ class DeviceMixin(object): # {{{
|
||||
loc[4] |= self.book_db_uuid_path_map[id]
|
||||
return loc
|
||||
|
||||
def set_books_in_library(self, booklists, reset=False):
|
||||
def set_books_in_library(self, booklists, reset=False, add_as_step_to_job=None):
|
||||
'''
|
||||
Set the ondevice indications in the device database.
|
||||
This method should be called before book_on_device is called, because
|
||||
@ -1487,7 +1511,7 @@ class DeviceMixin(object): # {{{
|
||||
plugboards = self.library_view.model().db.prefs.get('plugboards', {})
|
||||
self.device_manager.sync_booklists(
|
||||
FunctionDispatcher(self.metadata_synced), booklists,
|
||||
plugboards)
|
||||
plugboards, add_as_step_to_job)
|
||||
return update_metadata
|
||||
# }}}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user