diff --git a/src/calibre/gui2/progress_indicator/QProgressIndicator.cpp b/src/calibre/gui2/progress_indicator/QProgressIndicator.cpp index 6cee373cc7..9d5a9e19a8 100644 --- a/src/calibre/gui2/progress_indicator/QProgressIndicator.cpp +++ b/src/calibre/gui2/progress_indicator/QProgressIndicator.cpp @@ -9,18 +9,21 @@ #include #include #include +#include -QProgressIndicator::QProgressIndicator(QWidget* parent, int size) +QProgressIndicator::QProgressIndicator(QWidget* parent, int size, int interval) : QWidget(parent), m_angle(0), m_timerId(-1), - m_delay(80), - m_displaySize(size), - m_displayedWhenStopped(true), - m_color(Qt::black) + m_delay(interval), + m_displaySize(size, size), + m_dark(Qt::black), + m_light(Qt::white) { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); setFocusPolicy(Qt::NoFocus); + m_dark = this->palette().color(QPalette::WindowText); + m_light = this->palette().color(QPalette::Window); } bool QProgressIndicator::isAnimated () const @@ -28,24 +31,22 @@ bool QProgressIndicator::isAnimated () const return (m_timerId != -1); } -void QProgressIndicator::setDisplayedWhenStopped(bool state) +void QProgressIndicator::setDisplaySize(QSize size) { - m_displayedWhenStopped = state; - - update(); + setSizeHint(size); } - -void QProgressIndicator::setDisplaySize(int size) +void QProgressIndicator::setSizeHint(int size) +{ + setSizeHint(QSize(size, size)); +} +void QProgressIndicator::setSizeHint(QSize size) { m_displaySize = size; update(); } -bool QProgressIndicator::isDisplayedWhenStopped() const -{ - return m_displayedWhenStopped; -} + void QProgressIndicator::startAnimation() { @@ -54,6 +55,7 @@ void QProgressIndicator::startAnimation() if (m_timerId == -1) m_timerId = startTimer(m_delay); } +void QProgressIndicator::start() { startAnimation(); } void QProgressIndicator::stopAnimation() { @@ -64,6 +66,7 @@ void QProgressIndicator::stopAnimation() update(); } +void QProgressIndicator::stop() { stopAnimation(); } void QProgressIndicator::setAnimationDelay(int delay) { @@ -76,16 +79,16 @@ void QProgressIndicator::setAnimationDelay(int delay) m_timerId = startTimer(m_delay); } -void QProgressIndicator::setColor(const QColor & color) +void QProgressIndicator::set_colors(const QColor & dark, const QColor & light) { - m_color = color; + m_dark = dark; m_light = light; update(); } QSize QProgressIndicator::sizeHint() const { - return QSize(m_displaySize, m_displaySize); + return m_displaySize; } int QProgressIndicator::heightForWidth(int w) const @@ -95,40 +98,15 @@ int QProgressIndicator::heightForWidth(int w) const void QProgressIndicator::timerEvent(QTimerEvent * /*event*/) { - m_angle = (m_angle+30)%360; + m_angle = (m_angle-2)%360; update(); } void QProgressIndicator::paintEvent(QPaintEvent * /*event*/) { - if (!m_displayedWhenStopped && !isAnimated()) - return; - - int width = qMin(this->width(), this->height()); - - QPainter p(this); - p.setRenderHint(QPainter::Antialiasing); - - int outerRadius = (width-1)*0.5; - int innerRadius = (width-1)*0.5*0.38; - - int capsuleHeight = outerRadius - innerRadius; - int capsuleWidth = (width > 32 ) ? capsuleHeight *.23 : capsuleHeight *.35; - int capsuleRadius = capsuleWidth/2; - - for (int i=0; i<12; i++) - { - QColor color = m_color; - color.setAlphaF(1.0f - (i/12.0f)); - p.setPen(Qt::NoPen); - p.setBrush(color); - p.save(); - p.translate(rect().center()); - p.rotate(m_angle - i*30.0f); - p.drawRoundedRect(-capsuleWidth*0.5, -(innerRadius+capsuleHeight), capsuleWidth, capsuleHeight, capsuleRadius, capsuleRadius); - p.restore(); - } + QPainter painter(this); + draw_snake_spinner(painter, this->rect(), m_angle, m_light, m_dark); } static inline QByteArray detectDesktopEnvironment() @@ -282,3 +260,27 @@ class TouchMenuStyle: public QProxyStyle { void set_touch_menu_style(QWidget *widget, int margin) { widget->setStyle(new TouchMenuStyle(margin)); } + +void draw_snake_spinner(QPainter &painter, QRect rect, int angle, const QColor & light, const QColor & dark) { + painter.save(); + painter.setRenderHint(QPainter::Antialiasing); + if (rect.width() > rect.height()) { + int delta = (rect.width() - rect.height()) / 2; + rect = rect.adjusted(delta, 0, -delta, 0); + } else if (rect.height() > rect.width()) { + int delta = (rect.height() - rect.width()) / 2; + rect = rect.adjusted(0, delta, 0, -delta); + } + int disc_width = std::max(3, std::min(rect.width() / 10, 8)); + QRect drawing_rect(rect.x() + disc_width, rect.y() + disc_width, rect.width() - 2 * disc_width, rect.height() - 2 *disc_width); + int gap = 60; // degrees + QConicalGradient gradient(drawing_rect.center(), angle - gap / 2); + gradient.setColorAt((360 - gap/2)/360.0, light); + gradient.setColorAt(0, dark); + + QPen pen(QBrush(gradient), disc_width); + pen.setCapStyle(Qt::RoundCap); + painter.setPen(pen); + painter.drawArc(drawing_rect, angle * 16, (360 - gap) * 16); + painter.restore(); +} diff --git a/src/calibre/gui2/progress_indicator/QProgressIndicator.h b/src/calibre/gui2/progress_indicator/QProgressIndicator.h index 95390cc6cf..a383a02aae 100644 --- a/src/calibre/gui2/progress_indicator/QProgressIndicator.h +++ b/src/calibre/gui2/progress_indicator/QProgressIndicator.h @@ -3,11 +3,12 @@ #include #include #include +#include -/*! +/*! \class QProgressIndicator - \brief The QProgressIndicator class lets an application display a progress indicator to show that a lengthy task is under way. - + \brief The QProgressIndicator class lets an application display a progress indicator to show that a lengthy task is under way. + Progress indicators are indeterminate and do nothing more than spin to show that the application is busy. \sa QProgressBar */ @@ -15,11 +16,9 @@ class QProgressIndicator : public QWidget { Q_OBJECT Q_PROPERTY(int delay READ animationDelay WRITE setAnimationDelay) - Q_PROPERTY(bool displayedWhenStopped READ isDisplayedWhenStopped WRITE setDisplayedWhenStopped) - Q_PROPERTY(QColor color READ color WRITE setColor) - Q_PROPERTY(int displaySize READ displaySize WRITE setDisplaySize) + Q_PROPERTY(QSize displaySize READ displaySize WRITE setDisplaySize) public: - QProgressIndicator(QWidget* parent = 0, int size = 64); + QProgressIndicator(QWidget* parent = 0, int size = 64, int interval = 10); /*! Returns the delay between animation steps. \return The number of milliseconds between animation steps. By default, the animation delay is set to 80 milliseconds. @@ -33,65 +32,52 @@ public: */ bool isAnimated () const; - /*! Returns a Boolean value indicating whether the receiver shows itself even when it is not animating. - \return Return true if the progress indicator shows itself even when it is not animating. By default, it returns false. - \sa setDisplayedWhenStopped - */ - bool isDisplayedWhenStopped() const; - - /*! Returns the color of the component. - \sa setColor - */ - const QColor & color() const { return m_color; } - virtual QSize sizeHint() const; int heightForWidth(int w) const; - int displaySize() const { return m_displaySize; } + QSize displaySize() const { return m_displaySize; } public slots: /*! Starts the spin animation. \sa stopAnimation isAnimated */ void startAnimation(); + void start(); /*! Stops the spin animation. \sa startAnimation isAnimated */ void stopAnimation(); + void stop(); /*! Sets the delay between animation steps. Setting the \a delay to a value larger than 40 slows the animation, while setting the \a delay to a smaller value speeds it up. - \param delay The delay, in milliseconds. - \sa animationDelay + \param delay The delay, in milliseconds. + \sa animationDelay */ void setAnimationDelay(int delay); - /*! Sets whether the component hides itself when it is not animating. - \param state The animation state. Set false to hide the progress indicator when it is not animating; otherwise true. - \sa isDisplayedWhenStopped - */ - void setDisplayedWhenStopped(bool state); - /*! Sets the color of the components to the given color. \sa color */ - void setColor(const QColor & color); + void set_colors(const QColor & dark, const QColor & light); /*! Set the size of this widget (used by sizeHint) * \sa displaySize */ - void setDisplaySize(int size); + void setDisplaySize(QSize size); + void setSizeHint(int size); + void setSizeHint(QSize size); protected: - virtual void timerEvent(QTimerEvent * event); + virtual void timerEvent(QTimerEvent * event); virtual void paintEvent(QPaintEvent * event); private: int m_angle; int m_timerId; int m_delay; - int m_displaySize; - bool m_displayedWhenStopped; - QColor m_color; + QSize m_displaySize; + QColor m_dark, m_light; }; int load_style(QHash icon_map); void set_no_activate_on_click(QWidget *widget); void set_touch_menu_style(QWidget *widget, int margin=14); +void draw_snake_spinner(QPainter &painter, QRect rect, int angle, const QColor & light, const QColor & dark); diff --git a/src/calibre/gui2/progress_indicator/QProgressIndicator.sip b/src/calibre/gui2/progress_indicator/QProgressIndicator.sip index 00596b6ad1..11e9bdcb7e 100644 --- a/src/calibre/gui2/progress_indicator/QProgressIndicator.sip +++ b/src/calibre/gui2/progress_indicator/QProgressIndicator.sip @@ -6,9 +6,11 @@ %Import QtWidgets/QtWidgetsmod.sip %ModuleHeaderCode +#include int load_style(QHash icon_map); void set_no_activate_on_click(QWidget *widget); void set_touch_menu_style(QWidget *widget, int margin); +void draw_snake_spinner(QPainter &painter, QRect rect, int angle, const QColor & light, const QColor & dark); %End class QProgressIndicator : QWidget { @@ -19,34 +21,32 @@ class QProgressIndicator : QWidget { public: - QProgressIndicator(QWidget *parent /TransferThis/ = 0, int size = 64); + QProgressIndicator(QWidget *parent /TransferThis/ = 0, int size = 64, int interval = 10); int animationDelay() const; bool isAnimated () const; - bool isDisplayedWhenStopped() const; - - const QColor & color() const; - virtual QSize sizeHint() const; int heightForWidth(int w) const; - int displaySize() const; + QSize displaySize() const; public slots: void startAnimation(); + void start(); void stopAnimation(); + void stop(); void setAnimationDelay(int delay); - void setDisplayedWhenStopped(bool state); + void set_colors(const QColor & dark, const QColor & light); - void setColor(const QColor & color); - - void setDisplaySize(int size); + void setDisplaySize(QSize size); + void setSizeHint(int size); + void setSizeHint(QSize size); protected: @@ -59,3 +59,4 @@ protected: int load_style(QHash icon_map); void set_no_activate_on_click(QWidget *widget); void set_touch_menu_style(QWidget *widget, int margin=20); +void draw_snake_spinner(QPainter &painter, QRect rect, int angle, const QColor & light, const QColor & dark);