mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Show progress information in jobs dialog while downloading feeds
This commit is contained in:
parent
36484b906d
commit
77d65631a9
@ -35,7 +35,7 @@ def main(args=sys.argv, notification=None, handler=None):
|
||||
recipe_arg = args[1] if len(args) > 1 else None
|
||||
|
||||
tdir = PersistentTemporaryDirectory('_feeds2lrf')
|
||||
opts.output_dir = tdir
|
||||
opts.output_dir = tdir
|
||||
|
||||
recipe = run_recipe(opts, recipe_arg, parser, notification=notification, handler=handler)
|
||||
|
||||
@ -56,4 +56,4 @@ def main(args=sys.argv, notification=None, handler=None):
|
||||
return 0
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
sys.exit(main())
|
||||
|
@ -10,7 +10,7 @@ Module to implement the Cover Flow feature
|
||||
import sys, os
|
||||
|
||||
from PyQt4.QtGui import QImage, QSizePolicy
|
||||
from PyQt4.QtCore import Qt, QSize, SIGNAL
|
||||
from PyQt4.QtCore import Qt, QSize, SIGNAL, QObject
|
||||
|
||||
from calibre import pictureflow
|
||||
|
||||
@ -49,7 +49,7 @@ if pictureflow is not None:
|
||||
def __init__(self, model, buffer=20):
|
||||
pictureflow.FlowImages.__init__(self)
|
||||
self.model = model
|
||||
self.connect(self.model, SIGNAL('modelReset()'), self.reset)
|
||||
QObject.connect(self.model, SIGNAL('modelReset()'), self.reset)
|
||||
|
||||
def count(self):
|
||||
return self.model.count()
|
||||
@ -76,9 +76,9 @@ if pictureflow is not None:
|
||||
|
||||
def wheelEvent(self, ev):
|
||||
ev.accept()
|
||||
if ev.delta() > 0:
|
||||
if ev.delta() < 0:
|
||||
self.showNext()
|
||||
elif ev.delta() < 0:
|
||||
elif ev.delta() > 0:
|
||||
self.showPrevious()
|
||||
|
||||
|
||||
@ -105,4 +105,4 @@ if __name__ == '__main__':
|
||||
|
||||
w.show()
|
||||
cf.setFocus(Qt.OtherFocusReason)
|
||||
sys.exit(app.exec_())
|
||||
sys.exit(app.exec_())
|
||||
|
@ -2,12 +2,31 @@ __license__ = 'GPL v3'
|
||||
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||
'''Display active jobs'''
|
||||
|
||||
from PyQt4.QtCore import Qt, QObject, SIGNAL
|
||||
from PyQt4.QtGui import QDialog
|
||||
from PyQt4.QtCore import Qt, QObject, SIGNAL, QSize, QString
|
||||
from PyQt4.QtGui import QDialog, QAbstractItemDelegate, QStyleOptionProgressBarV2, \
|
||||
QApplication, QStyle
|
||||
|
||||
from calibre.gui2.dialogs.jobs_ui import Ui_JobsDialog
|
||||
from calibre import __appname__
|
||||
|
||||
class ProgressBarDelegate(QAbstractItemDelegate):
|
||||
|
||||
def sizeHint(self, option, index):
|
||||
return QSize(120, 30)
|
||||
|
||||
def paint(self, painter, option, index):
|
||||
opts = QStyleOptionProgressBarV2()
|
||||
opts.rect = option.rect
|
||||
opts.minimum = 1
|
||||
opts.maximum = 100
|
||||
opts.textVisible = True
|
||||
percent, ok = index.model().data(index, Qt.DisplayRole).toInt()
|
||||
if not ok:
|
||||
percent = 0
|
||||
opts.progress = percent
|
||||
opts.text = QString(_('Unavailable') if percent == 0 else '%d%%'%percent)
|
||||
QApplication.style().drawControl(QStyle.CE_ProgressBar, opts, painter)
|
||||
|
||||
class JobsDialog(QDialog, Ui_JobsDialog):
|
||||
def __init__(self, window, model):
|
||||
QDialog.__init__(self, window)
|
||||
@ -23,6 +42,8 @@ class JobsDialog(QDialog, Ui_JobsDialog):
|
||||
self.kill_job)
|
||||
QObject.connect(self, SIGNAL('kill_job(int, PyQt_PyObject)'),
|
||||
self.jobs_view.model().kill_job)
|
||||
self.pb_delegate = ProgressBarDelegate(self)
|
||||
self.jobs_view.setItemDelegateForColumn(2, self.pb_delegate)
|
||||
|
||||
def kill_job(self):
|
||||
for index in self.jobs_view.selectedIndexes():
|
||||
|
@ -224,6 +224,18 @@ class JobManager(QAbstractTableModel):
|
||||
if isinstance(job, ConversionJob):
|
||||
yield job
|
||||
|
||||
def update_progress(self, id, percent):
|
||||
row = -1
|
||||
for collection in (self.running_jobs, self.waiting_jobs, self.finished_jobs):
|
||||
for job in collection:
|
||||
row += 1
|
||||
if job.id == id:
|
||||
job.percent_done = percent
|
||||
index = self.index(row, 2)
|
||||
self.emit(SIGNAL('dataChanged(QModelIndex, QModelIndex)'), index, index)
|
||||
return
|
||||
|
||||
|
||||
def create_job(self, job_class, description, slot, priority, *args, **kwargs):
|
||||
self.next_id += 1
|
||||
id = self.next_id
|
||||
@ -312,8 +324,7 @@ class JobManager(QAbstractTableModel):
|
||||
st = [_('Working'), _('Waiting')][status]
|
||||
return QVariant(st)
|
||||
if col == 2:
|
||||
p = str(job.percent_done) + r'%' if job.percent_done > 0 else _('Unavailable')
|
||||
return QVariant(p)
|
||||
return QVariant(int(100*job.percent_done))
|
||||
if col == 3:
|
||||
if job.start_time is None:
|
||||
return NONE
|
||||
|
@ -250,7 +250,7 @@ class Main(MainWindow, Ui_MainWindow):
|
||||
index = self.library_view.model().index(index, 0)
|
||||
self.library_view.setCurrentIndex(index)
|
||||
if hasattr(index, 'row') and self.cover_flow.isVisible() and self.cover_flow.currentSlide() != index.row():
|
||||
self.cover_flow.setCurrentSlide(index.row())
|
||||
self.cover_flow.setCurrentSlide(index.row())
|
||||
|
||||
def another_instance_wants_to_talk(self, msg):
|
||||
if msg.startswith('launched:'):
|
||||
@ -266,6 +266,16 @@ class Main(MainWindow, Ui_MainWindow):
|
||||
elif msg.startswith('refreshdb:'):
|
||||
self.library_view.model().resort()
|
||||
self.library_view.model().research()
|
||||
elif msg.startswith('progress:'):
|
||||
try:
|
||||
fields = msg.split(':')
|
||||
job_id, percent = fields[1:3]
|
||||
job_id, percent = int(job_id), float(percent)
|
||||
self.job_manager.update_progress(job_id, percent)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
print msg
|
||||
|
||||
|
||||
def current_view(self):
|
||||
@ -288,7 +298,7 @@ class Main(MainWindow, Ui_MainWindow):
|
||||
'''
|
||||
Called when a device is connected to the computer.
|
||||
'''
|
||||
if connected:
|
||||
if connected:
|
||||
self.device_manager = DeviceManager(device)
|
||||
self.job_manager.run_device_job(self.info_read, self.device_manager.info_func())
|
||||
self.set_default_thumbnail(device.THUMBNAIL_HEIGHT)
|
||||
|
@ -12,12 +12,25 @@ from calibre.ebooks.lrf.web.convert_from import main as web2lrf
|
||||
from calibre.ebooks.lrf.feeds.convert_from import main as feeds2lrf
|
||||
from calibre.gui2.lrf_renderer.main import main as lrfviewer
|
||||
from calibre import iswindows, __appname__
|
||||
try:
|
||||
from calibre.utils.single_qt_application import SingleApplication
|
||||
except:
|
||||
SingleApplication = None
|
||||
|
||||
sa = None
|
||||
job_id = None
|
||||
|
||||
def report_progress(percent, msg=''):
|
||||
if sa is not None and job_id is not None:
|
||||
msg = 'progress:%s:%f:%s'%(job_id, percent, msg)
|
||||
sa.send_message(msg)
|
||||
|
||||
|
||||
PARALLEL_FUNCS = {
|
||||
'any2lrf' : partial(any2lrf, gui_mode=True),
|
||||
'web2lrf' : web2lrf,
|
||||
'lrfviewer' : lrfviewer,
|
||||
'feeds2lrf' : feeds2lrf,
|
||||
'feeds2lrf' : partial(feeds2lrf, notification=report_progress),
|
||||
}
|
||||
|
||||
python = sys.executable
|
||||
@ -46,7 +59,7 @@ class Server(object):
|
||||
def __init__(self):
|
||||
self.tdir = tempfile.mkdtemp('', '%s_IPC_'%__appname__)
|
||||
atexit.register(cleanup, self.tdir)
|
||||
self.kill_jobs = []
|
||||
self.kill_jobs = []
|
||||
|
||||
def kill(self, job_id):
|
||||
'''
|
||||
@ -90,7 +103,7 @@ class Server(object):
|
||||
os.mkdir(job_dir)
|
||||
|
||||
job_data = os.path.join(job_dir, 'job_data.pickle')
|
||||
cPickle.dump((func, args, kwdargs), open(job_data, 'wb'), -1)
|
||||
cPickle.dump((job_id, func, args, kwdargs), open(job_data, 'wb'), -1)
|
||||
prefix = ''
|
||||
if hasattr(sys, 'frameworks_dir'):
|
||||
fd = getattr(sys, 'frameworks_dir')
|
||||
@ -116,23 +129,26 @@ class Server(object):
|
||||
p.poll()
|
||||
|
||||
|
||||
output.close()
|
||||
output.close()
|
||||
job_result = os.path.join(job_dir, 'job_result.pickle')
|
||||
if not os.path.exists(job_result):
|
||||
result, exception, traceback = None, ('ParallelRuntimeError',
|
||||
result, exception, traceback = None, ('ParallelRuntimeError',
|
||||
'The worker process died unexpectedly.'), ''
|
||||
else:
|
||||
else:
|
||||
result, exception, traceback = cPickle.load(open(job_result, 'rb'))
|
||||
log = open(output.name, 'rb').read()
|
||||
|
||||
return result, exception, traceback, log
|
||||
|
||||
|
||||
|
||||
def run_job(job_data):
|
||||
global sa, job_id
|
||||
if SingleApplication is not None:
|
||||
sa = SingleApplication('calibre GUI')
|
||||
job_data = binascii.unhexlify(job_data)
|
||||
base = os.path.dirname(job_data)
|
||||
job_result = os.path.join(base, 'job_result.pickle')
|
||||
func, args, kwdargs = cPickle.load(open(job_data, 'rb'))
|
||||
job_id, func, args, kwdargs = cPickle.load(open(job_data, 'rb'))
|
||||
func = PARALLEL_FUNCS[func]
|
||||
exception, tb = None, None
|
||||
try:
|
||||
@ -154,3 +170,5 @@ def main():
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
from calibre.utils.single_qt_application import SingleApplication
|
||||
|
@ -9,7 +9,7 @@ applications using a local socket.
|
||||
'''
|
||||
import atexit
|
||||
|
||||
from PyQt4.QtCore import QByteArray, QDataStream, QIODevice, SIGNAL, QObject, Qt
|
||||
from PyQt4.QtCore import QByteArray, QDataStream, QIODevice, SIGNAL, QObject, Qt, QString
|
||||
from PyQt4.QtNetwork import QLocalSocket, QLocalServer
|
||||
|
||||
timeout_read = 5000
|
||||
@ -20,7 +20,7 @@ def write_message(socket, message, timeout = 5000):
|
||||
out = QDataStream(block, QIODevice.WriteOnly)
|
||||
|
||||
out.writeInt32(0)
|
||||
out.writeString(message)
|
||||
out.writeString(QString(message))
|
||||
out.device().seek(0)
|
||||
out.writeInt32(len(message))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user