From 8323e8b8b25f725ba79e5b3db6aeb2de8cb52c9e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 12 Sep 2009 12:52:27 -0600 Subject: [PATCH] Jobs dialog:Allow stopping of waiting jobs and add Stop all jobs button --- src/calibre/gui2/dialogs/jobs.ui | 11 +++++++++-- src/calibre/gui2/jobs.py | 11 ++++++++++- src/calibre/gui2/tools.py | 3 +-- src/calibre/utils/ipc/job.py | 1 + src/calibre/utils/ipc/server.py | 26 +++++++++++++++++++------- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/calibre/gui2/dialogs/jobs.ui b/src/calibre/gui2/dialogs/jobs.ui index de2d78db73..e2e345ca28 100644 --- a/src/calibre/gui2/dialogs/jobs.ui +++ b/src/calibre/gui2/dialogs/jobs.ui @@ -14,7 +14,7 @@ Active Jobs - + :/images/jobs.svg:/images/jobs.svg @@ -57,6 +57,13 @@ + + + + Stop &all jobs + + + @@ -67,7 +74,7 @@ - + diff --git a/src/calibre/gui2/jobs.py b/src/calibre/gui2/jobs.py index 2cd25e1b4e..1d86910e15 100644 --- a/src/calibre/gui2/jobs.py +++ b/src/calibre/gui2/jobs.py @@ -193,6 +193,12 @@ class JobManager(QAbstractTableModel): _('Job has already run')).exec_() self.server.kill_job(job) + def kill_all_jobs(self): + for job in self.jobs: + if isinstance(job, DeviceJob) or job.duration is not None: + continue + self.server.kill_job(job) + def terminate_all_jobs(self): self.server.killall() @@ -230,6 +236,8 @@ class JobsDialog(QDialog, Ui_JobsDialog): self.kill_job) self.connect(self.details_button, SIGNAL('clicked()'), self.show_details) + self.connect(self.stop_all_jobs_button, SIGNAL('clicked()'), + self.kill_all_jobs) self.connect(self, SIGNAL('kill_job(int, PyQt_PyObject)'), self.jobs_view.model().kill_job) self.pb_delegate = ProgressBarDelegate(self) @@ -247,7 +255,8 @@ class JobsDialog(QDialog, Ui_JobsDialog): self.jobs_view.show_details(index) return - + def kill_all_jobs(self): + self.model.kill_all_jobs() def closeEvent(self, e): self.jobs_view.write_settings() diff --git a/src/calibre/gui2/tools.py b/src/calibre/gui2/tools.py index 4ff6cccb25..33bf465fd2 100644 --- a/src/calibre/gui2/tools.py +++ b/src/calibre/gui2/tools.py @@ -156,8 +156,6 @@ def convert_bulk_ebook(parent, db, book_ids, out_format=None): dtitle = repr(mi.title) desc = _('Convert book %d of %d (%s)') % (i + 1, total, dtitle) - desc = _('Convert book %d of %d (%s)') % (i + 1, total, repr(mi.title)) - args = [in_file, out_file.name, lrecs] temp_files.append(out_file) jobs.append(('gui_convert', args, desc, d.output_format.upper(), book_id, temp_files)) @@ -178,6 +176,7 @@ def convert_bulk_ebook(parent, db, book_ids, out_format=None): 'source format was found.') % (len(res), total), msg).exec_() + jobs.reverse() return jobs, changed, bad def fetch_scheduled_recipe(recipe, script): diff --git a/src/calibre/utils/ipc/job.py b/src/calibre/utils/ipc/job.py index ec33c54231..16ce85ace6 100644 --- a/src/calibre/utils/ipc/job.py +++ b/src/calibre/utils/ipc/job.py @@ -30,6 +30,7 @@ class BaseJob(object): self.done2 = None self.killed = False self.failed = False + self.kill_on_start = False self.start_time = None self.result = None self.duration = None diff --git a/src/calibre/utils/ipc/server.py b/src/calibre/utils/ipc/server.py index c00f2479c9..4d2c4496bb 100644 --- a/src/calibre/utils/ipc/server.py +++ b/src/calibre/utils/ipc/server.py @@ -170,6 +170,7 @@ class Server(Thread): except Empty: pass + # Get notifications from worker process for worker in self.workers: while True: try: @@ -179,6 +180,7 @@ class Server(Thread): except Empty: break + # Remove finished jobs for worker in [w for w in self.workers if not w.is_alive]: self.workers.remove(worker) job = worker.job @@ -191,19 +193,27 @@ class Server(Thread): job.duration = time.time() - job.start_time self.changed_jobs_queue.put(job) + # Start new workers if len(self.pool) + len(self.workers) < self.pool_size: try: self.pool.append(self.launch_worker()) except Exception: pass + # Start waiting jobs if len(self.pool) > 0 and len(self.waiting_jobs) > 0: job = self.waiting_jobs.pop() - worker = self.pool.pop() job.start_time = time.time() - worker.start_job(job) - self.workers.append(worker) - job.log_path = worker.log_path + if job.kill_on_start: + job.duration = 0.0 + job.returncode = 1 + job.killed = job.failed = True + job.result = None + else: + worker = self.pool.pop() + worker.start_job(job) + self.workers.append(worker) + job.log_path = worker.log_path self.changed_jobs_queue.put(job) while True: @@ -217,11 +227,13 @@ class Server(Thread): self.kill_queue.put(job) def killall(self): - for job in self.workers: - self.kill_queue.put(job) + for worker in self.workers: + self.kill_queue.put(worker.job) def _kill_job(self, job): - if job.start_time is None: return + if job.start_time is None: + job.kill_on_start = True + return for worker in self.workers: if job is worker.job: worker.kill()