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
|
recipe_arg = args[1] if len(args) > 1 else None
|
||||||
|
|
||||||
tdir = PersistentTemporaryDirectory('_feeds2lrf')
|
tdir = PersistentTemporaryDirectory('_feeds2lrf')
|
||||||
opts.output_dir = tdir
|
opts.output_dir = tdir
|
||||||
|
|
||||||
recipe = run_recipe(opts, recipe_arg, parser, notification=notification, handler=handler)
|
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
|
return 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
@ -10,7 +10,7 @@ Module to implement the Cover Flow feature
|
|||||||
import sys, os
|
import sys, os
|
||||||
|
|
||||||
from PyQt4.QtGui import QImage, QSizePolicy
|
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
|
from calibre import pictureflow
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ if pictureflow is not None:
|
|||||||
def __init__(self, model, buffer=20):
|
def __init__(self, model, buffer=20):
|
||||||
pictureflow.FlowImages.__init__(self)
|
pictureflow.FlowImages.__init__(self)
|
||||||
self.model = model
|
self.model = model
|
||||||
self.connect(self.model, SIGNAL('modelReset()'), self.reset)
|
QObject.connect(self.model, SIGNAL('modelReset()'), self.reset)
|
||||||
|
|
||||||
def count(self):
|
def count(self):
|
||||||
return self.model.count()
|
return self.model.count()
|
||||||
@ -76,9 +76,9 @@ if pictureflow is not None:
|
|||||||
|
|
||||||
def wheelEvent(self, ev):
|
def wheelEvent(self, ev):
|
||||||
ev.accept()
|
ev.accept()
|
||||||
if ev.delta() > 0:
|
if ev.delta() < 0:
|
||||||
self.showNext()
|
self.showNext()
|
||||||
elif ev.delta() < 0:
|
elif ev.delta() > 0:
|
||||||
self.showPrevious()
|
self.showPrevious()
|
||||||
|
|
||||||
|
|
||||||
@ -105,4 +105,4 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
w.show()
|
w.show()
|
||||||
cf.setFocus(Qt.OtherFocusReason)
|
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>'
|
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
'''Display active jobs'''
|
'''Display active jobs'''
|
||||||
|
|
||||||
from PyQt4.QtCore import Qt, QObject, SIGNAL
|
from PyQt4.QtCore import Qt, QObject, SIGNAL, QSize, QString
|
||||||
from PyQt4.QtGui import QDialog
|
from PyQt4.QtGui import QDialog, QAbstractItemDelegate, QStyleOptionProgressBarV2, \
|
||||||
|
QApplication, QStyle
|
||||||
|
|
||||||
from calibre.gui2.dialogs.jobs_ui import Ui_JobsDialog
|
from calibre.gui2.dialogs.jobs_ui import Ui_JobsDialog
|
||||||
from calibre import __appname__
|
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):
|
class JobsDialog(QDialog, Ui_JobsDialog):
|
||||||
def __init__(self, window, model):
|
def __init__(self, window, model):
|
||||||
QDialog.__init__(self, window)
|
QDialog.__init__(self, window)
|
||||||
@ -23,6 +42,8 @@ class JobsDialog(QDialog, Ui_JobsDialog):
|
|||||||
self.kill_job)
|
self.kill_job)
|
||||||
QObject.connect(self, SIGNAL('kill_job(int, PyQt_PyObject)'),
|
QObject.connect(self, SIGNAL('kill_job(int, PyQt_PyObject)'),
|
||||||
self.jobs_view.model().kill_job)
|
self.jobs_view.model().kill_job)
|
||||||
|
self.pb_delegate = ProgressBarDelegate(self)
|
||||||
|
self.jobs_view.setItemDelegateForColumn(2, self.pb_delegate)
|
||||||
|
|
||||||
def kill_job(self):
|
def kill_job(self):
|
||||||
for index in self.jobs_view.selectedIndexes():
|
for index in self.jobs_view.selectedIndexes():
|
||||||
|
@ -224,6 +224,18 @@ class JobManager(QAbstractTableModel):
|
|||||||
if isinstance(job, ConversionJob):
|
if isinstance(job, ConversionJob):
|
||||||
yield job
|
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):
|
def create_job(self, job_class, description, slot, priority, *args, **kwargs):
|
||||||
self.next_id += 1
|
self.next_id += 1
|
||||||
id = self.next_id
|
id = self.next_id
|
||||||
@ -312,8 +324,7 @@ class JobManager(QAbstractTableModel):
|
|||||||
st = [_('Working'), _('Waiting')][status]
|
st = [_('Working'), _('Waiting')][status]
|
||||||
return QVariant(st)
|
return QVariant(st)
|
||||||
if col == 2:
|
if col == 2:
|
||||||
p = str(job.percent_done) + r'%' if job.percent_done > 0 else _('Unavailable')
|
return QVariant(int(100*job.percent_done))
|
||||||
return QVariant(p)
|
|
||||||
if col == 3:
|
if col == 3:
|
||||||
if job.start_time is None:
|
if job.start_time is None:
|
||||||
return NONE
|
return NONE
|
||||||
|
@ -250,7 +250,7 @@ class Main(MainWindow, Ui_MainWindow):
|
|||||||
index = self.library_view.model().index(index, 0)
|
index = self.library_view.model().index(index, 0)
|
||||||
self.library_view.setCurrentIndex(index)
|
self.library_view.setCurrentIndex(index)
|
||||||
if hasattr(index, 'row') and self.cover_flow.isVisible() and self.cover_flow.currentSlide() != index.row():
|
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):
|
def another_instance_wants_to_talk(self, msg):
|
||||||
if msg.startswith('launched:'):
|
if msg.startswith('launched:'):
|
||||||
@ -266,6 +266,16 @@ class Main(MainWindow, Ui_MainWindow):
|
|||||||
elif msg.startswith('refreshdb:'):
|
elif msg.startswith('refreshdb:'):
|
||||||
self.library_view.model().resort()
|
self.library_view.model().resort()
|
||||||
self.library_view.model().research()
|
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):
|
def current_view(self):
|
||||||
@ -288,7 +298,7 @@ class Main(MainWindow, Ui_MainWindow):
|
|||||||
'''
|
'''
|
||||||
Called when a device is connected to the computer.
|
Called when a device is connected to the computer.
|
||||||
'''
|
'''
|
||||||
if connected:
|
if connected:
|
||||||
self.device_manager = DeviceManager(device)
|
self.device_manager = DeviceManager(device)
|
||||||
self.job_manager.run_device_job(self.info_read, self.device_manager.info_func())
|
self.job_manager.run_device_job(self.info_read, self.device_manager.info_func())
|
||||||
self.set_default_thumbnail(device.THUMBNAIL_HEIGHT)
|
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.ebooks.lrf.feeds.convert_from import main as feeds2lrf
|
||||||
from calibre.gui2.lrf_renderer.main import main as lrfviewer
|
from calibre.gui2.lrf_renderer.main import main as lrfviewer
|
||||||
from calibre import iswindows, __appname__
|
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 = {
|
PARALLEL_FUNCS = {
|
||||||
'any2lrf' : partial(any2lrf, gui_mode=True),
|
'any2lrf' : partial(any2lrf, gui_mode=True),
|
||||||
'web2lrf' : web2lrf,
|
'web2lrf' : web2lrf,
|
||||||
'lrfviewer' : lrfviewer,
|
'lrfviewer' : lrfviewer,
|
||||||
'feeds2lrf' : feeds2lrf,
|
'feeds2lrf' : partial(feeds2lrf, notification=report_progress),
|
||||||
}
|
}
|
||||||
|
|
||||||
python = sys.executable
|
python = sys.executable
|
||||||
@ -46,7 +59,7 @@ class Server(object):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.tdir = tempfile.mkdtemp('', '%s_IPC_'%__appname__)
|
self.tdir = tempfile.mkdtemp('', '%s_IPC_'%__appname__)
|
||||||
atexit.register(cleanup, self.tdir)
|
atexit.register(cleanup, self.tdir)
|
||||||
self.kill_jobs = []
|
self.kill_jobs = []
|
||||||
|
|
||||||
def kill(self, job_id):
|
def kill(self, job_id):
|
||||||
'''
|
'''
|
||||||
@ -90,7 +103,7 @@ class Server(object):
|
|||||||
os.mkdir(job_dir)
|
os.mkdir(job_dir)
|
||||||
|
|
||||||
job_data = os.path.join(job_dir, 'job_data.pickle')
|
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 = ''
|
prefix = ''
|
||||||
if hasattr(sys, 'frameworks_dir'):
|
if hasattr(sys, 'frameworks_dir'):
|
||||||
fd = getattr(sys, 'frameworks_dir')
|
fd = getattr(sys, 'frameworks_dir')
|
||||||
@ -116,23 +129,26 @@ class Server(object):
|
|||||||
p.poll()
|
p.poll()
|
||||||
|
|
||||||
|
|
||||||
output.close()
|
output.close()
|
||||||
job_result = os.path.join(job_dir, 'job_result.pickle')
|
job_result = os.path.join(job_dir, 'job_result.pickle')
|
||||||
if not os.path.exists(job_result):
|
if not os.path.exists(job_result):
|
||||||
result, exception, traceback = None, ('ParallelRuntimeError',
|
result, exception, traceback = None, ('ParallelRuntimeError',
|
||||||
'The worker process died unexpectedly.'), ''
|
'The worker process died unexpectedly.'), ''
|
||||||
else:
|
else:
|
||||||
result, exception, traceback = cPickle.load(open(job_result, 'rb'))
|
result, exception, traceback = cPickle.load(open(job_result, 'rb'))
|
||||||
log = open(output.name, 'rb').read()
|
log = open(output.name, 'rb').read()
|
||||||
|
|
||||||
return result, exception, traceback, log
|
return result, exception, traceback, log
|
||||||
|
|
||||||
|
|
||||||
def run_job(job_data):
|
def run_job(job_data):
|
||||||
|
global sa, job_id
|
||||||
|
if SingleApplication is not None:
|
||||||
|
sa = SingleApplication('calibre GUI')
|
||||||
job_data = binascii.unhexlify(job_data)
|
job_data = binascii.unhexlify(job_data)
|
||||||
base = os.path.dirname(job_data)
|
base = os.path.dirname(job_data)
|
||||||
job_result = os.path.join(base, 'job_result.pickle')
|
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]
|
func = PARALLEL_FUNCS[func]
|
||||||
exception, tb = None, None
|
exception, tb = None, None
|
||||||
try:
|
try:
|
||||||
@ -154,3 +170,5 @@ def main():
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
|
||||||
|
from calibre.utils.single_qt_application import SingleApplication
|
||||||
|
@ -9,7 +9,7 @@ applications using a local socket.
|
|||||||
'''
|
'''
|
||||||
import atexit
|
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
|
from PyQt4.QtNetwork import QLocalSocket, QLocalServer
|
||||||
|
|
||||||
timeout_read = 5000
|
timeout_read = 5000
|
||||||
@ -20,7 +20,7 @@ def write_message(socket, message, timeout = 5000):
|
|||||||
out = QDataStream(block, QIODevice.WriteOnly)
|
out = QDataStream(block, QIODevice.WriteOnly)
|
||||||
|
|
||||||
out.writeInt32(0)
|
out.writeInt32(0)
|
||||||
out.writeString(message)
|
out.writeString(QString(message))
|
||||||
out.device().seek(0)
|
out.device().seek(0)
|
||||||
out.writeInt32(len(message))
|
out.writeInt32(len(message))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user