1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-23 01:09:42 +01:00

Fix qpixmap mode of AnimatedSpinner

This commit is contained in:
Leo Franchi 2012-04-27 18:58:24 -04:00
parent 65b01ffbca
commit 91ebe57dd2
3 changed files with 117 additions and 47 deletions

View File

@ -170,9 +170,8 @@ AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option,
Q_ASSERT( m_loadingSpinners[ index ] );
if ( m_loadingSpinners[ index ] )
{
painter->setOpacity( 1.0 );
const QPixmap pm = m_loadingSpinners[index]->pixmap();
painter->drawPixmap( checkRect.adjusted( -2, -2, 2, 2 ), pm );
painter->drawPixmap( checkRect, pm );
}
}
@ -681,7 +680,10 @@ void
AccountDelegate::startInstalling( const QPersistentModelIndex& idx )
{
qDebug() << "START INSTALLING:" << idx.data( Qt::DisplayRole ).toString();
AnimatedSpinner* anim = new AnimatedSpinner( 0 );
QStyleOptionViewItemV4 opt;
initStyleOption( &opt, idx );
AnimatedSpinner* anim = new AnimatedSpinner( checkRectForIndex( opt, idx ).size(), true );
_detail::Closure* closure = NewClosure( anim, SIGNAL( requestUpdate() ), this, SLOT( doUpdateIndex( const QPersistentModelIndex& ) ), idx );
closure->setAutoDelete( false );

View File

@ -28,17 +28,67 @@
#include <QtGui/QPaintEvent>
#include <QtGui/QShowEvent>
AnimatedSpinner::AnimatedSpinner(QWidget *parent)
: QWidget(parent)
AnimatedSpinner::AnimatedSpinner( QWidget *parent )
: QWidget( parent )
, m_showHide( new QTimeLine )
, m_animation( new QTimeLine )
, m_currentIndex( -1 )
{
init();
m_radius = 10;
m_armLength = sizeHint().width()/2 - m_radius;
m_armWidth = 5;
m_border = 3;
m_armRect = QRect( m_radius, 0, m_armLength, m_armWidth );
}
AnimatedSpinner::AnimatedSpinner( const QSize size, bool autoStart )
: QWidget()
, m_showHide( new QTimeLine )
, m_animation( new QTimeLine )
, m_currentIndex( -1 )
{
m_pixmap = QPixmap( size );
m_pixmap.fill( Qt::transparent );
init();
if ( size.width() < 30 )
{
m_radius = 4;
m_armLength = size.width()/2 - m_radius;
m_armWidth = 2;
m_border = 2;
m_armRect = QRect( m_radius, 0, m_armLength, m_armWidth );
}
else
{
m_radius = 10;
m_armLength = size.width()/2 - m_radius;
m_armWidth = 5;
m_border = 3;
m_armRect = QRect( m_radius, 0, m_armLength, m_armWidth );
}
if ( autoStart )
fadeIn();
}
void
AnimatedSpinner::init()
{
m_showHide->setDuration( 300 );
m_showHide->setStartFrame( 0 );
m_showHide->setEndFrame( 100 );
m_showHide->setUpdateInterval( 20 );
connect( m_showHide, SIGNAL( frameChanged( int ) ), this, SLOT( update() ) );
if( parentWidget() )
connect( m_showHide, SIGNAL( frameChanged( int ) ), this, SLOT( update() ) );
else
connect( m_showHide, SIGNAL( frameChanged( int ) ), this, SLOT( updatePixmap() ) );
connect( m_showHide, SIGNAL( finished() ), this, SLOT( hideFinished() ) );
m_animation->setDuration( 1000 );
@ -53,12 +103,6 @@ AnimatedSpinner::AnimatedSpinner(QWidget *parent)
m_colors.resize( segmentCount() );
hide();
if ( !parentWidget() )
{
m_pixmap = QPixmap( sizeHint() );
}
}
@ -66,7 +110,6 @@ void
AnimatedSpinner::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
if ( parentWidget() )
{
QPoint center( ( parentWidget()->width() / 2 ) - ( width() / 2 ), ( parentWidget()->height() / 2 ) - ( height() / 2 ) );
@ -77,43 +120,47 @@ AnimatedSpinner::paintEvent(QPaintEvent *event)
}
}
QPainter p;
if ( parentWidget() )
{
p.begin(this);
}
else
{
m_pixmap.fill( Qt::transparent );
QPainter p(this);
drawFrame( &p, rect() );
}
p.begin(&m_pixmap);
}
void
AnimatedSpinner::updatePixmap()
{
Q_ASSERT( !m_pixmap.isNull() );
QPainter p( &m_pixmap );
m_pixmap.fill( Qt::transparent );
drawFrame( &p, m_pixmap.rect() );
p.end();
emit requestUpdate();
}
void
AnimatedSpinner::drawFrame( QPainter* p, const QRect& rect )
{
if ( m_showHide->state() == QTimeLine::Running )
{
// showing or hiding
p.setOpacity( (qreal)m_showHide->currentValue() );
p->setOpacity( (qreal)m_showHide->currentValue() );
}
const int radius = 10;
const int armLength = width()/2 - radius;
const int armWidth = 5;
const int border = 3;
const QRectF armRect( radius, 0, armLength, armWidth );
p->setRenderHint(QPainter::Antialiasing, true);
p.setRenderHint(QPainter::Antialiasing, true);
p->translate( rect.center() ); // center
p.translate(width() / 2, height() / 2); // center
const qreal stepRadius = (360 + 2*armWidth) / segmentCount();
p.rotate( stepRadius );
const qreal stepRadius = (360 + 2*m_armWidth) / segmentCount();
p->rotate( stepRadius );
for (int segment = 0; segment < segmentCount(); ++segment) {
p.rotate(stepRadius);
p->rotate(stepRadius);
QPainterPath arm;
arm.addRoundedRect( armRect.adjusted( 0, -armWidth/2., 0, -armWidth/2 ), border, border );
arm.addRoundedRect( m_armRect.adjusted( 0, -m_armWidth/2., 0, -m_armWidth/2 ), m_border, m_border );
p.fillPath( arm, colorForSegment( segment ) );
p->fillPath( arm, colorForSegment( segment ) );
}
}
@ -121,17 +168,20 @@ AnimatedSpinner::paintEvent(QPaintEvent *event)
void
AnimatedSpinner::fadeIn()
{
if ( isVisible() )
if ( parentWidget() && isVisible() )
return;
show();
m_animation->start();
m_showHide->setDirection( QTimeLine::Forward );
if ( m_showHide->state() != QTimeLine::Running )
m_showHide->start();
if ( parentWidget() )
show();
else
updatePixmap();
}
@ -150,8 +200,11 @@ AnimatedSpinner::hideFinished()
{
if ( m_showHide->direction() == QTimeLine::Backward )
{
hide();
m_animation->stop();
if ( parentWidget() )
hide();
else
updatePixmap();
}
}
@ -188,7 +241,11 @@ AnimatedSpinner::frameChanged( int frame )
++running;
cur = --cur < 0 ? m_colors.size() - 1 : cur;
}
update();
if ( parentWidget() )
update();
else
updatePixmap();
}

View File

@ -25,6 +25,7 @@
#include <QtCore/QSize>
#include <QtGui/QColor>
#include <QtGui/QPixmap>
#include <QPainter>
class QTimeLine;
class QHideEvent;
@ -32,18 +33,21 @@ class QShowEvent;
class QPaintEvent;
class QTimerEvent;
/**
If you don't pass a parent QWidget, this spinner will
draw into the pixmap instead. If you do, the pixmap will
be invalid.
*/
class DLLEXPORT AnimatedSpinner : public QWidget
{
Q_OBJECT
public:
AnimatedSpinner( QWidget *parent = 0 );
explicit AnimatedSpinner( QWidget *parent = 0 ); // widget mode
AnimatedSpinner( const QSize size, bool autoStart ); // pixmap mode
QSize sizeHint() const;
/**
If you don't pass a parent QWidget, this spinner will
draw into the pixmap instead. If you do, this will be invalid.
*/
QPixmap pixmap() const { return m_pixmap; }
public slots:
@ -57,17 +61,24 @@ protected:
void paintEvent(QPaintEvent *event);
private slots:
void updatePixmap();
void hideFinished();
void frameChanged( int );
private:
void init();
void drawFrame( QPainter* p, const QRect& rect );
int segmentCount() const;
QColor colorForSegment( int segment ) const;
QTimeLine* m_showHide;
QTimeLine* m_animation;
// to tweak
int m_radius, m_armLength, m_armWidth, m_border;
QRect m_armRect;
int m_currentIndex;
QVector<qreal> m_colors;
QPixmap m_pixmap;