diff --git a/resources.qrc b/resources.qrc
index 602774165..575b389c9 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -143,5 +143,6 @@
data/images/process-stop.png
data/icons/tomahawk-icon-128x128-grayscale.png
data/images/collection.png
+ data/images/loading-animation-dark.gif
diff --git a/src/AccountDelegate.cpp b/src/AccountDelegate.cpp
index 5e9e94ad0..4362d2519 100644
--- a/src/AccountDelegate.cpp
+++ b/src/AccountDelegate.cpp
@@ -27,6 +27,8 @@
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
+#include "utils/chasewidget.h"
+#include "utils/closure.h"
#define CHILD_ACCOUNT_HEIGHT 24
@@ -158,7 +160,23 @@ AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option,
QRect checkRect = QRect( leftEdge, checkboxYPos, WRENCH_SIZE, WRENCH_SIZE );
QStyleOptionViewItemV4 opt2 = opt;
opt2.rect = checkRect;
- drawCheckBox( opt2, painter, opt.widget );
+
+ if ( !m_loadingSpinners.contains( index ) )
+ {
+ drawCheckBox( opt2, painter, opt.widget );
+ }
+ else
+ {
+ Q_ASSERT( m_loadingSpinners[ index ] );
+ if ( m_loadingSpinners[ index ] )
+ {
+ painter->setOpacity( 1.0 );
+ const QPixmap pm = QPixmap::grabWidget( m_loadingSpinners[ index ] );
+ painter->drawPixmap( checkRect.adjusted( -2, -2, 2, 2 ), pm );
+ }
+ }
+
+
leftEdge += WRENCH_SIZE + PADDING / 2;
// Pixmap
@@ -183,6 +201,7 @@ AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option,
topt.pos = confRect.topLeft();
drawConfigWrench( painter, opt, topt );
+
m_cachedConfigRects[ index ] = confRect;
rightEdge = confRect.left();
@@ -662,6 +681,13 @@ void
AccountDelegate::startInstalling( const QPersistentModelIndex& idx )
{
qDebug() << "START INSTALLING:" << idx.data( Qt::DisplayRole ).toString();
+ ChaseWidget* anim = new ChaseWidget( QApplication::topLevelWidgets().first() );
+ _detail::Closure* closure = NewClosure( anim, SIGNAL( requestUpdate() ), this, SLOT( doUpdateIndex( const QPersistentModelIndex& ) ), idx );
+ closure->setAutoDelete( false );
+
+ m_loadingSpinners[ idx ] = anim;
+
+ update( idx );
}
@@ -669,5 +695,19 @@ void
AccountDelegate::doneInstalling ( const QPersistentModelIndex& idx )
{
qDebug() << "STOP INSTALLING:" << idx.data( Qt::DisplayRole ).toString();
+ Q_ASSERT( m_loadingSpinners.contains( idx ) );
+ if ( !m_loadingSpinners.contains( idx ) )
+ return;
+ delete m_loadingSpinners.take( idx );
+
+ update( idx );
}
+
+
+void
+AccountDelegate::doUpdateIndex( const QPersistentModelIndex& idx )
+{
+ emit update( idx );
+}
+
diff --git a/src/AccountDelegate.h b/src/AccountDelegate.h
index cb2e37cc9..f6a4a873e 100644
--- a/src/AccountDelegate.h
+++ b/src/AccountDelegate.h
@@ -22,6 +22,8 @@
#include
#include "accounts/AccountModel.h"
+class ChaseWidget;
+
namespace Tomahawk
{
namespace Accounts
@@ -42,6 +44,8 @@ public slots:
void startInstalling( const QPersistentModelIndex& idx );
void doneInstalling ( const QPersistentModelIndex& idx );
+ void doUpdateIndex( const QPersistentModelIndex& idx );
+
protected:
virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
@@ -68,7 +72,7 @@ private:
mutable QHash< QPersistentModelIndex, QRect > m_cachedStarRects;
mutable QHash< QPersistentModelIndex, QRect > m_cachedConfigRects;
mutable QHash< QPersistentModelIndex, QSize > m_sizeHints;
- mutable QHash< QPersistentModelIndex, QMovie* > m_loadingSpinners;
+ mutable QHash< QPersistentModelIndex, ChaseWidget* > m_loadingSpinners;
mutable int m_accountRowHeight;
};
diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt
index 230d4a792..0ad71153f 100644
--- a/src/libtomahawk/CMakeLists.txt
+++ b/src/libtomahawk/CMakeLists.txt
@@ -122,6 +122,7 @@ set( libGuiSources
utils/closure.cpp
utils/PixmapDelegateFader.cpp
utils/SmartPointerList.h
+ utils/chasewidget.cpp
widgets/animatedcounterlabel.cpp
widgets/checkdirtree.cpp
diff --git a/src/libtomahawk/accounts/AccountModelFilterProxy.cpp b/src/libtomahawk/accounts/AccountModelFilterProxy.cpp
index 5aa005e6c..1a559faed 100644
--- a/src/libtomahawk/accounts/AccountModelFilterProxy.cpp
+++ b/src/libtomahawk/accounts/AccountModelFilterProxy.cpp
@@ -36,8 +36,8 @@ void
AccountModelFilterProxy::setSourceModel( QAbstractItemModel* sourceModel )
{
connect( sourceModel, SIGNAL( scrollTo( QModelIndex ) ), this, SLOT( onScrollTo( QModelIndex ) ) );
- connect( sourceModel, SIGNAL( startInstalling( QPersistentModelIndex ) ), this, SIGNAL( startInstalling( QPersistentModelIndex ) ) );
- connect( sourceModel, SIGNAL( doneInstalling( QPersistentModelIndex ) ), this, SIGNAL( doneInstalling( QPersistentModelIndex ) ) );
+ connect( sourceModel, SIGNAL( startInstalling( QPersistentModelIndex ) ), this, SLOT( onStartInstalling( QPersistentModelIndex ) ) );
+ connect( sourceModel, SIGNAL( doneInstalling( QPersistentModelIndex ) ), this, SLOT( onDoneInstalling( QPersistentModelIndex ) ) );
QSortFilterProxyModel::setSourceModel( sourceModel );
}
@@ -72,3 +72,17 @@ AccountModelFilterProxy::onScrollTo( const QModelIndex& idx )
{
emit scrollTo( mapFromSource( idx ) );
}
+
+
+void
+AccountModelFilterProxy::onDoneInstalling( const QPersistentModelIndex& idx )
+{
+ emit doneInstalling( mapFromSource( idx ) );
+}
+
+
+void
+AccountModelFilterProxy::onStartInstalling( const QPersistentModelIndex& idx )
+{
+ emit startInstalling( mapFromSource( idx ) );
+}
diff --git a/src/libtomahawk/accounts/AccountModelFilterProxy.h b/src/libtomahawk/accounts/AccountModelFilterProxy.h
index 527a8b067..73c1a410c 100644
--- a/src/libtomahawk/accounts/AccountModelFilterProxy.h
+++ b/src/libtomahawk/accounts/AccountModelFilterProxy.h
@@ -49,6 +49,9 @@ protected:
private slots:
void onScrollTo( const QModelIndex& idx );
+ void onStartInstalling( const QPersistentModelIndex& idx );
+ void onDoneInstalling( const QPersistentModelIndex& idx );
+
private:
Tomahawk::Accounts::AccountType m_filterType;
};
diff --git a/src/libtomahawk/playlist/trackview.cpp b/src/libtomahawk/playlist/trackview.cpp
index 7939596b1..20410cad3 100644
--- a/src/libtomahawk/playlist/trackview.cpp
+++ b/src/libtomahawk/playlist/trackview.cpp
@@ -31,6 +31,7 @@
#include "context/ContextWidget.h"
#include "widgets/overlaywidget.h"
#include "dynamic/widgets/LoadingSpinner.h"
+#include "utils/chasewidget.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#include "utils/closure.h"
@@ -50,7 +51,7 @@ TrackView::TrackView( QWidget* parent )
, m_delegate( 0 )
, m_header( new TrackHeader( this ) )
, m_overlay( new OverlayWidget( this ) )
- , m_loadingSpinner( new LoadingSpinner( this ) )
+ , m_loadingSpinner( new ChaseWidget( this ) )
, m_resizing( false )
, m_dragging( false )
, m_updateContextView( true )
@@ -157,7 +158,7 @@ TrackView::setTrackModel( TrackModel* model )
setHeaderHidden( true );
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
break;
-
+
default:
setHeaderHidden( false );
setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
diff --git a/src/libtomahawk/playlist/trackview.h b/src/libtomahawk/playlist/trackview.h
index 4b1b4e527..f2ac5d389 100644
--- a/src/libtomahawk/playlist/trackview.h
+++ b/src/libtomahawk/playlist/trackview.h
@@ -31,6 +31,7 @@
class QAction;
class LoadingSpinner;
+class ChaseWidget;
class TrackHeader;
class TrackModel;
class TrackProxyModel;
@@ -57,7 +58,7 @@ public:
TrackHeader* header() const { return m_header; }
OverlayWidget* overlay() const { return m_overlay; }
Tomahawk::ContextMenu* contextMenu() const { return m_contextMenu; }
- LoadingSpinner* loadingSpinner() const { return m_loadingSpinner; }
+ ChaseWidget* loadingSpinner() const { return m_loadingSpinner; }
QModelIndex hoveredIndex() const { return m_hoveredIndex; }
QModelIndex contextMenuIndex() const { return m_contextMenuIndex; }
@@ -119,7 +120,7 @@ private:
PlaylistItemDelegate* m_delegate;
TrackHeader* m_header;
OverlayWidget* m_overlay;
- LoadingSpinner* m_loadingSpinner;
+ ChaseWidget* m_loadingSpinner;
bool m_resizing;
bool m_dragging;
@@ -133,7 +134,7 @@ private:
Tomahawk::query_ptr m_autoPlaying;
Tomahawk::ContextMenu* m_contextMenu;
-
+
QTimer m_timer;
};
diff --git a/src/libtomahawk/utils/chasewidget.cpp b/src/libtomahawk/utils/chasewidget.cpp
new file mode 100644
index 000000000..8acb66736
--- /dev/null
+++ b/src/libtomahawk/utils/chasewidget.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "chasewidget.h"
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+ChaseWidget::ChaseWidget(QWidget *parent, QPixmap pixmap, bool pixmapEnabled)
+ : QWidget(parent)
+ , m_segment(0)
+ , m_delay(100)
+ , m_step(40)
+ , m_timerId(-1)
+ , m_animated(false)
+ , m_pixmap(pixmap)
+ , m_pixmapEnabled(pixmapEnabled)
+ , m_showHide( new QTimeLine )
+{
+ 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() ) );
+ connect( m_showHide, SIGNAL( finished() ), this, SLOT( hideFinished() ) );
+
+ hide();
+
+}
+
+void ChaseWidget::setAnimated(bool value)
+{
+ if (m_animated == value)
+ return;
+ m_animated = value;
+ if (m_timerId != -1) {
+ killTimer(m_timerId);
+ m_timerId = -1;
+ }
+ if (m_animated) {
+ m_segment = 0;
+ m_timerId = startTimer(m_delay);
+ }
+ update();
+}
+
+void ChaseWidget::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event);
+
+ if ( parentWidget() )
+ {
+ QPoint center( ( parentWidget()->width() / 2 ) - ( width() / 2 ), ( parentWidget()->height() / 2 ) - ( height() / 2 ) );
+ if ( center != pos() )
+ {
+ move( center );
+ return;
+ }
+ }
+
+ QPainter p(this);
+
+ if ( m_showHide->state() == QTimeLine::Running )
+ {
+ // showing or hiding
+ p.setOpacity( (qreal)m_showHide->currentValue() );
+ }
+
+ if (m_pixmapEnabled && !m_pixmap.isNull()) {
+ p.drawPixmap(0, 0, m_pixmap);
+ return;
+ }
+
+ const int extent = qMin(width() - 8, height() - 8);
+ const int displ = extent / 4;
+ const int ext = extent / 4 - 1;
+
+ p.setRenderHint(QPainter::Antialiasing, true);
+
+ if(m_animated)
+ p.setPen(Qt::gray);
+ else
+ p.setPen(QPen(palette().dark().color()));
+
+ p.translate(width() / 2, height() / 2); // center
+
+ for (int segment = 0; segment < segmentCount(); ++segment) {
+ p.rotate(QApplication::isRightToLeft() ? m_step : -m_step);
+ if(m_animated)
+ p.setBrush(colorForSegment(segment));
+ else
+ p.setBrush(palette().background());
+ p.drawEllipse(QRect(displ, -ext / 2, ext, ext));
+ }
+}
+
+void ChaseWidget::fadeIn()
+{
+ if ( isVisible() )
+ return;
+
+ show();
+
+ setAnimated( true );
+ m_showHide->setDirection( QTimeLine::Forward );
+
+ if ( m_showHide->state() != QTimeLine::Running )
+ m_showHide->start();
+}
+
+void ChaseWidget::fadeOut()
+{
+ m_showHide->setDirection( QTimeLine::Backward );
+
+ if ( m_showHide->state() != QTimeLine::Running )
+ m_showHide->start();
+}
+
+void ChaseWidget::hideFinished()
+{
+ if ( m_showHide->direction() == QTimeLine::Backward )
+ {
+ hide();
+ setAnimated(false);
+ }
+}
+
+QSize ChaseWidget::sizeHint() const
+{
+ return QSize(64, 64);
+}
+
+void ChaseWidget::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == m_timerId) {
+ ++m_segment;
+ update();
+ emit requestUpdate();
+ }
+ QWidget::timerEvent(event);
+}
+
+QColor ChaseWidget::colorForSegment(int seg) const
+{
+ int index = ((seg + m_segment) % segmentCount());
+ int comp = qMax(0, 255 - (index * (255 / segmentCount())));
+ return QColor(comp, comp, comp, 255);
+}
+
+int ChaseWidget::segmentCount() const
+{
+ return 360 / m_step;
+}
+
+void ChaseWidget::setPixmapEnabled(bool enable)
+{
+ m_pixmapEnabled = enable;
+}
+
diff --git a/src/libtomahawk/utils/chasewidget.h b/src/libtomahawk/utils/chasewidget.h
new file mode 100644
index 000000000..0c3450ac7
--- /dev/null
+++ b/src/libtomahawk/utils/chasewidget.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CHASEWIDGET_H
+#define CHASEWIDGET_H
+
+#include "dllmacro.h"
+
+#include
+
+#include
+#include
+#include
+
+class QTimeLine;
+class QHideEvent;
+class QShowEvent;
+class QPaintEvent;
+class QTimerEvent;
+
+class DLLEXPORT ChaseWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ ChaseWidget(QWidget *parent = 0, QPixmap pixmap = QPixmap(), bool pixmapEnabled = false);
+
+ void setPixmapEnabled(bool enable);
+ QSize sizeHint() const;
+
+public slots:
+ void fadeIn();
+ void fadeOut();
+
+signals:
+ void requestUpdate();
+
+protected:
+ void paintEvent(QPaintEvent *event);
+ void timerEvent(QTimerEvent *event);
+
+private slots:
+ void hideFinished();
+
+private:
+ void setAnimated(bool value);
+ int segmentCount() const;
+ QColor colorForSegment(int segment) const;
+
+ QTimeLine* m_showHide;
+
+ int m_segment;
+ int m_delay;
+ int m_step;
+ int m_timerId;
+ bool m_animated;
+ QPixmap m_pixmap;
+ bool m_pixmapEnabled;
+};
+
+#endif
diff --git a/src/libtomahawk/widgets/searchwidget.cpp b/src/libtomahawk/widgets/searchwidget.cpp
index 0ccbda4ab..8add731b0 100644
--- a/src/libtomahawk/widgets/searchwidget.cpp
+++ b/src/libtomahawk/widgets/searchwidget.cpp
@@ -26,6 +26,7 @@
#include "sourcelist.h"
#include "viewmanager.h"
#include "dynamic/widgets/LoadingSpinner.h"
+#include "utils/chasewidget.h"
#include "playlist/albummodel.h"
#include "playlist/playlistmodel.h"
#include "widgets/overlaywidget.h"
@@ -146,7 +147,7 @@ SearchWidget::onResultsFound( const QList& results )
q->addResults( rl );
m_resultsModel->append( q );
-
+
artists << result->artist();
albums << result->album();
}