diff --git a/src/calibre/gui2/dialogs/jobs.ui b/src/calibre/gui2/dialogs/jobs.ui
index 95d0585cf0..0893a8be8b 100644
--- a/src/calibre/gui2/dialogs/jobs.ui
+++ b/src/calibre/gui2/dialogs/jobs.ui
@@ -17,8 +17,8 @@
:/images/jobs.png:/images/jobs.png
-
- -
+
+
-
Qt::NoContextMenu
@@ -40,27 +40,48 @@
- -
+
-
&Stop selected jobs
- -
+
-
+
+
+ &Hide selected jobs
+
+
+
+ -
Show job &details
- -
+
-
+
+
+ Show &all jobs
+
+
+
+ -
Stop &all non device jobs
+ -
+
+
+ &Hide all jobs
+
+
+
diff --git a/src/calibre/gui2/jobs.py b/src/calibre/gui2/jobs.py
index 07b05afdc3..ae3f93647c 100644
--- a/src/calibre/gui2/jobs.py
+++ b/src/calibre/gui2/jobs.py
@@ -14,7 +14,7 @@ from PyQt4.Qt import (QAbstractTableModel, QVariant, QModelIndex, Qt,
QTimer, pyqtSignal, QIcon, QDialog, QAbstractItemDelegate, QApplication,
QSize, QStyleOptionProgressBarV2, QString, QStyle, QToolTip, QFrame,
QHBoxLayout, QVBoxLayout, QSizePolicy, QLabel, QCoreApplication, QAction,
- QByteArray)
+ QByteArray, QSortFilterProxyModel)
from calibre.utils.ipc.server import Server
from calibre.utils.ipc.job import ParallelJob
@@ -26,6 +26,8 @@ from calibre.gui2.dialogs.job_view_ui import Ui_Dialog
from calibre.gui2.progress_indicator import ProgressIndicator
from calibre.gui2.threaded_jobs import ThreadedJobServer, ThreadedJob
+HIDE_ROLE = Qt.UserRole + 1
+
class JobManager(QAbstractTableModel): # {{{
job_added = pyqtSignal(int)
@@ -91,7 +93,7 @@ class JobManager(QAbstractTableModel): # {{{
def data(self, index, role):
try:
- if role not in (Qt.DisplayRole, Qt.DecorationRole):
+ if role not in (Qt.DisplayRole, Qt.DecorationRole, HIDE_ROLE):
return NONE
row, col = index.row(), index.column()
job = self.jobs[row]
@@ -121,6 +123,9 @@ class JobManager(QAbstractTableModel): # {{{
if job.killed or job.failed:
return self.error_icon
return self.done_icon
+ if role == HIDE_ROLE:
+ return QVariant('h' if getattr(job, 'hidden_in_gui', False)
+ else 's')
except:
import traceback
traceback.print_exc()
@@ -251,6 +256,18 @@ class JobManager(QAbstractTableModel): # {{{
else:
job.kill_on_start = True
+ def hide_jobs(self, rows):
+ for r in rows:
+ self.jobs[r].hidden_in_gui = True
+ for r in rows:
+ self.dataChanged.emit(self.index(r, 0), self.index(r, 0))
+
+ def show_hidden_jobs(self):
+ for j in self.jobs:
+ j.hidden_in_gui = False
+ for r in xrange(len(self.jobs)):
+ self.dataChanged.emit(self.index(r, 0), self.index(r, 0))
+
def kill_job(self, row, view):
job = self.jobs[row]
if isinstance(job, DeviceJob):
@@ -450,8 +467,12 @@ class JobsDialog(QDialog, Ui_JobsDialog):
QDialog.__init__(self, window)
Ui_JobsDialog.__init__(self)
self.setupUi(self)
- self.jobs_view.setModel(model)
self.model = model
+ self.proxy_model = QSortFilterProxyModel(self)
+ self.proxy_model.setSourceModel(self.model)
+ self.proxy_model.setFilterRole(HIDE_ROLE)
+ self.proxy_model.setFilterFixedString('s')
+ self.jobs_view.setModel(self.proxy_model)
self.setWindowModality(Qt.NonModal)
self.setWindowTitle(__appname__ + _(' - Jobs'))
self.details_button.clicked.connect(self.show_details)
@@ -461,6 +482,9 @@ class JobsDialog(QDialog, Ui_JobsDialog):
self.jobs_view.setItemDelegateForColumn(2, self.pb_delegate)
self.jobs_view.doubleClicked.connect(self.show_job_details)
self.jobs_view.horizontalHeader().setMovable(True)
+ self.hide_button.clicked.connect(self.hide_selected)
+ self.hide_all_button.clicked.connect(self.hide_all)
+ self.show_button.clicked.connect(self.show_hidden)
self.restore_state()
def restore_state(self):
@@ -486,11 +510,13 @@ class JobsDialog(QDialog, Ui_JobsDialog):
pass
def show_job_details(self, index):
- row = index.row()
- job = self.jobs_view.model().row_to_job(row)
- d = DetailView(self, job)
- d.exec_()
- d.timer.stop()
+ index = self.proxy_model.mapToSource(index)
+ if index.isValid():
+ row = index.row()
+ job = self.model.row_to_job(row)
+ d = DetailView(self, job)
+ d.exec_()
+ d.timer.stop()
def show_details(self, *args):
index = self.jobs_view.currentIndex()
@@ -498,8 +524,10 @@ class JobsDialog(QDialog, Ui_JobsDialog):
self.show_job_details(index)
def kill_job(self, *args):
- rows = [index.row() for index in
+ indices = [self.proxy_model.mapToSource(index) for index in
self.jobs_view.selectionModel().selectedRows()]
+ indices = [i for i in indices if i.isValid()]
+ rows = [index.row() for index in indices]
if not rows:
return error_dialog(self, _('No job'),
_('No job selected'), show=True)
@@ -517,6 +545,26 @@ class JobsDialog(QDialog, Ui_JobsDialog):
_('Do you really want to stop all non-device jobs?')):
self.model.kill_all_jobs()
+ def hide_selected(self, *args):
+ indices = [self.proxy_model.mapToSource(index) for index in
+ self.jobs_view.selectionModel().selectedRows()]
+ indices = [i for i in indices if i.isValid()]
+ rows = [index.row() for index in indices]
+ if not rows:
+ return error_dialog(self, _('No job'),
+ _('No job selected'), show=True)
+ self.model.hide_jobs(rows)
+ self.proxy_model.reset()
+
+ def hide_all(self, *args):
+ self.model.hide_jobs(list(xrange(0,
+ self.model.rowCount(QModelIndex()))))
+ self.proxy_model.reset()
+
+ def show_hidden(self, *args):
+ self.model.show_hidden_jobs()
+ self.proxy_model.reset()
+
def closeEvent(self, e):
self.save_state()
return QDialog.closeEvent(self, e)