Jobs list: Add the ability to hide jobs, useful if you have run a lot of jobs and the list is getting crowded. Fixes #883734 (Clear Jobs)

This commit is contained in:
Kovid Goyal 2011-11-15 11:25:00 +05:30
parent 1d23886c12
commit efd0209ce6
2 changed files with 83 additions and 14 deletions

View File

@ -17,8 +17,8 @@
<iconset resource="../../../../resources/images.qrc"> <iconset resource="../../../../resources/images.qrc">
<normaloff>:/images/jobs.png</normaloff>:/images/jobs.png</iconset> <normaloff>:/images/jobs.png</normaloff>:/images/jobs.png</iconset>
</property> </property>
<layout class="QVBoxLayout"> <layout class="QGridLayout" name="gridLayout">
<item> <item row="0" column="0" colspan="2">
<widget class="QTableView" name="jobs_view"> <widget class="QTableView" name="jobs_view">
<property name="contextMenuPolicy"> <property name="contextMenuPolicy">
<enum>Qt::NoContextMenu</enum> <enum>Qt::NoContextMenu</enum>
@ -40,27 +40,48 @@
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="1" column="0">
<widget class="QPushButton" name="kill_button"> <widget class="QPushButton" name="kill_button">
<property name="text"> <property name="text">
<string>&amp;Stop selected jobs</string> <string>&amp;Stop selected jobs</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="1" column="1">
<widget class="QPushButton" name="hide_button">
<property name="text">
<string>&amp;Hide selected jobs</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="details_button"> <widget class="QPushButton" name="details_button">
<property name="text"> <property name="text">
<string>Show job &amp;details</string> <string>Show job &amp;details</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="2" column="1">
<widget class="QPushButton" name="show_button">
<property name="text">
<string>Show &amp;all jobs</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="stop_all_jobs_button"> <widget class="QPushButton" name="stop_all_jobs_button">
<property name="text"> <property name="text">
<string>Stop &amp;all non device jobs</string> <string>Stop &amp;all non device jobs</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1">
<widget class="QPushButton" name="hide_all_button">
<property name="text">
<string>&amp;Hide all jobs</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources> <resources>

View File

@ -14,7 +14,7 @@ from PyQt4.Qt import (QAbstractTableModel, QVariant, QModelIndex, Qt,
QTimer, pyqtSignal, QIcon, QDialog, QAbstractItemDelegate, QApplication, QTimer, pyqtSignal, QIcon, QDialog, QAbstractItemDelegate, QApplication,
QSize, QStyleOptionProgressBarV2, QString, QStyle, QToolTip, QFrame, QSize, QStyleOptionProgressBarV2, QString, QStyle, QToolTip, QFrame,
QHBoxLayout, QVBoxLayout, QSizePolicy, QLabel, QCoreApplication, QAction, QHBoxLayout, QVBoxLayout, QSizePolicy, QLabel, QCoreApplication, QAction,
QByteArray) QByteArray, QSortFilterProxyModel)
from calibre.utils.ipc.server import Server from calibre.utils.ipc.server import Server
from calibre.utils.ipc.job import ParallelJob 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.progress_indicator import ProgressIndicator
from calibre.gui2.threaded_jobs import ThreadedJobServer, ThreadedJob from calibre.gui2.threaded_jobs import ThreadedJobServer, ThreadedJob
HIDE_ROLE = Qt.UserRole + 1
class JobManager(QAbstractTableModel): # {{{ class JobManager(QAbstractTableModel): # {{{
job_added = pyqtSignal(int) job_added = pyqtSignal(int)
@ -91,7 +93,7 @@ class JobManager(QAbstractTableModel): # {{{
def data(self, index, role): def data(self, index, role):
try: try:
if role not in (Qt.DisplayRole, Qt.DecorationRole): if role not in (Qt.DisplayRole, Qt.DecorationRole, HIDE_ROLE):
return NONE return NONE
row, col = index.row(), index.column() row, col = index.row(), index.column()
job = self.jobs[row] job = self.jobs[row]
@ -121,6 +123,9 @@ class JobManager(QAbstractTableModel): # {{{
if job.killed or job.failed: if job.killed or job.failed:
return self.error_icon return self.error_icon
return self.done_icon return self.done_icon
if role == HIDE_ROLE:
return QVariant('h' if getattr(job, 'hidden_in_gui', False)
else 's')
except: except:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
@ -251,6 +256,18 @@ class JobManager(QAbstractTableModel): # {{{
else: else:
job.kill_on_start = True 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): def kill_job(self, row, view):
job = self.jobs[row] job = self.jobs[row]
if isinstance(job, DeviceJob): if isinstance(job, DeviceJob):
@ -450,8 +467,12 @@ class JobsDialog(QDialog, Ui_JobsDialog):
QDialog.__init__(self, window) QDialog.__init__(self, window)
Ui_JobsDialog.__init__(self) Ui_JobsDialog.__init__(self)
self.setupUi(self) self.setupUi(self)
self.jobs_view.setModel(model)
self.model = 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.setWindowModality(Qt.NonModal)
self.setWindowTitle(__appname__ + _(' - Jobs')) self.setWindowTitle(__appname__ + _(' - Jobs'))
self.details_button.clicked.connect(self.show_details) 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.setItemDelegateForColumn(2, self.pb_delegate)
self.jobs_view.doubleClicked.connect(self.show_job_details) self.jobs_view.doubleClicked.connect(self.show_job_details)
self.jobs_view.horizontalHeader().setMovable(True) 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() self.restore_state()
def restore_state(self): def restore_state(self):
@ -486,11 +510,13 @@ class JobsDialog(QDialog, Ui_JobsDialog):
pass pass
def show_job_details(self, index): def show_job_details(self, index):
row = index.row() index = self.proxy_model.mapToSource(index)
job = self.jobs_view.model().row_to_job(row) if index.isValid():
d = DetailView(self, job) row = index.row()
d.exec_() job = self.model.row_to_job(row)
d.timer.stop() d = DetailView(self, job)
d.exec_()
d.timer.stop()
def show_details(self, *args): def show_details(self, *args):
index = self.jobs_view.currentIndex() index = self.jobs_view.currentIndex()
@ -498,8 +524,10 @@ class JobsDialog(QDialog, Ui_JobsDialog):
self.show_job_details(index) self.show_job_details(index)
def kill_job(self, *args): 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()] self.jobs_view.selectionModel().selectedRows()]
indices = [i for i in indices if i.isValid()]
rows = [index.row() for index in indices]
if not rows: if not rows:
return error_dialog(self, _('No job'), return error_dialog(self, _('No job'),
_('No job selected'), show=True) _('No job selected'), show=True)
@ -517,6 +545,26 @@ class JobsDialog(QDialog, Ui_JobsDialog):
_('Do you really want to stop all non-device jobs?')): _('Do you really want to stop all non-device jobs?')):
self.model.kill_all_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): def closeEvent(self, e):
self.save_state() self.save_state()
return QDialog.closeEvent(self, e) return QDialog.closeEvent(self, e)