diff --git a/src/calibre/gui2/actions/convert.py b/src/calibre/gui2/actions/convert.py index 34e03dc275..4289158b78 100644 --- a/src/calibre/gui2/actions/convert.py +++ b/src/calibre/gui2/actions/convert.py @@ -132,6 +132,7 @@ class ConvertAction(InterfaceAction): num = len(jobs) if num > 0: + self.gui.jobs_pointer.start() self.gui.status_bar.show_message(_('Starting conversion of %d book(s)') % num, 2000) diff --git a/src/calibre/gui2/job_indicator.py b/src/calibre/gui2/job_indicator.py new file mode 100644 index 0000000000..3767c0cfcf --- /dev/null +++ b/src/calibre/gui2/job_indicator.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai +from __future__ import (unicode_literals, division, absolute_import, + print_function) + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from PyQt4.Qt import (QPainter, Qt, QWidget, QPropertyAnimation, QRect, QPoint, + QColor, QEasingCurve, QBrush, QPainterPath, QPointF, + QPalette) + +from calibre.gui2 import config + +class Pointer(QWidget): + + def __init__(self, gui): + QWidget.__init__(self, gui) + self.setObjectName('jobs_pointer') + self.setVisible(False) + self.resize(100, 80) + self.animation = QPropertyAnimation(self, "geometry", self) + self.animation.setDuration(750) + self.animation.setLoopCount(2) + self.animation.setEasingCurve(QEasingCurve.Linear) + self.animation.finished.connect(self.hide) + + taily, heady = 0, 55 + self.arrow_path = QPainterPath(QPointF(40, taily)) + self.arrow_path.lineTo(40, heady) + self.arrow_path.lineTo(20, heady) + self.arrow_path.lineTo(50, self.height()) + self.arrow_path.lineTo(80, heady) + self.arrow_path.lineTo(60, heady) + self.arrow_path.lineTo(60, taily) + self.arrow_path.closeSubpath() + + c = self.palette().color(QPalette.Active, QPalette.WindowText) + self.color = QColor(c) + self.color.setAlpha(100) + self.brush = QBrush(self.color, Qt.SolidPattern) + + # from PyQt4.Qt import QTimer + # QTimer.singleShot(1000, self.start) + + @property + def gui(self): + return self.parent() + + def point_at(self, frac): + return (self.path.pointAtPercent(frac).toPoint() - + QPoint(self.rect().center().x(), self.height())) + + def rect_at(self, frac): + return QRect(self.point_at(frac), self.size()) + + def abspos(self, widget): + pos = widget.pos() + parent = widget.parent() + while parent is not self.gui: + pos += parent.pos() + parent = parent.parent() + return pos + + def start(self): + if config['disable_animations']: + return + self.setVisible(True) + self.raise_() + end = self.abspos(self.gui.jobs_button) + end = QPointF( end.x() + self.gui.jobs_button.width()/3.0, end.y()+20) + start = QPointF(end.x(), end.y() - 0.5*self.height()) + self.path = QPainterPath(QPointF(start)) + self.path.lineTo(end) + self.path.closeSubpath() + self.animation.setStartValue(self.rect_at(0.0)) + self.animation.setEndValue(self.rect_at(1.0)) + self.animation.setDirection(self.animation.Backward) + num_keys = 100 + for i in xrange(1, num_keys): + i /= num_keys + self.animation.setKeyValueAt(i, self.rect_at(i)) + self.animation.start() + + def paintEvent(self, ev): + p = QPainter(self) + p.setRenderHints(p.Antialiasing) + p.setBrush(self.brush) + p.setPen(Qt.NoPen) + p.drawPath(self.arrow_path) + p.end() + diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 28c9132071..db64969179 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -45,6 +45,7 @@ from calibre.gui2.auto_add import AutoAdder from calibre.library.sqlite import sqlite, DatabaseException from calibre.gui2.proceed import ProceedQuestion from calibre.gui2.dialogs.message_box import JobError +from calibre.gui2.job_indicator import Pointer class Listener(Thread): # {{{ @@ -109,6 +110,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ def __init__(self, opts, parent=None, gui_debug=None): global _gui MainWindow.__init__(self, opts, parent=parent, disable_automatic_gc=True) + self.jobs_pointer = Pointer(self) self.proceed_requested.connect(self.do_proceed, type=Qt.QueuedConnection) self.proceed_question = ProceedQuestion(self)