new class QgsAnimatedIcon

This commit is contained in:
Radim Blazek 2015-05-26 09:36:47 +02:00
parent 72c9830178
commit 0c4ea1f6e5
3 changed files with 93 additions and 33 deletions

View File

@ -145,7 +145,6 @@ class QgsDataItem : QObject
void emitDataChanged( );
void emitStateChanged( QgsDataItem* item, QgsDataItem::State oldState );
virtual void childrenCreated();
void setPopulatingIcon();
signals:
void beginInsertItems( QgsDataItem* parent, int first, int last );

View File

@ -43,6 +43,57 @@
#include "cpl_vsi.h"
#include "cpl_string.h"
QgsAnimatedIcon::QgsAnimatedIcon( const QString & iconPath )
: QObject()
, mCount( 0 )
, mMovie( 0 )
{
// QApplication as parent to ensure that it is deleted before QApplication
mMovie = new QMovie( QApplication::instance() );
if ( !iconPath.isEmpty() )
{
mMovie->setFileName( iconPath );
}
mMovie->setCacheMode( QMovie::CacheAll );
connect( mMovie, SIGNAL( frameChanged( int ) ), SLOT( onFrameChanged() ) );
}
QString QgsAnimatedIcon::iconPath() const
{
return mMovie->fileName();
}
void QgsAnimatedIcon::setIconPath( const QString & iconPath )
{
mMovie->setFileName( iconPath );
}
void QgsAnimatedIcon::onFrameChanged()
{
mIcon = QIcon( mMovie->currentPixmap() );
emit frameChanged();
}
void QgsAnimatedIcon::connectFrameChanged( const QObject * receiver, const char * method )
{
if ( connect( this, SIGNAL( frameChanged() ), receiver, method ) )
{
mCount++;
}
mMovie->setPaused( mCount == 0 );
QgsDebugMsg( QString( "mCount = %1" ).arg( mCount ) );
}
void QgsAnimatedIcon::disconnectFrameChanged( const QObject * receiver, const char * method )
{
if ( disconnect( this, SIGNAL( frameChanged() ), receiver, method ) )
{
mCount--;
}
mMovie->setPaused( mCount == 0 );
QgsDebugMsg( QString( "mCount = %1" ).arg( mCount ) );
}
// shared icons
const QIcon &QgsLayerItem::iconPoint()
{
@ -153,9 +204,7 @@ const QIcon &QgsZipItem::iconZip()
QMap<QString, QIcon> QgsDataItem::mIconMap = QMap<QString, QIcon>();
int QgsDataItem::mPopulatingCount = 0;
QMovie * QgsDataItem::mPopulatingMovie = 0;
QIcon QgsDataItem::mPopulatingIcon = QIcon();
QgsAnimatedIcon * QgsDataItem::mPopulatingIcon = 0;
QgsDataItem::QgsDataItem( QgsDataItem::Type type, QgsDataItem* parent, QString name, QString path )
// Do not pass parent to QObject, Qt would delete this when parent is deleted
@ -247,8 +296,8 @@ void QgsDataItem::moveToThread( QThread * targetThread )
QIcon QgsDataItem::icon()
{
if ( state() == Populating )
return mPopulatingIcon;
if ( state() == Populating && mPopulatingIcon )
return mPopulatingIcon->icon();
if ( !mIcon.isNull() )
return mIcon;
@ -574,11 +623,6 @@ bool QgsDataItem::equal( const QgsDataItem *other )
return false;
}
void QgsDataItem::setPopulatingIcon()
{
mPopulatingIcon = QIcon( mPopulatingMovie->currentPixmap() );
}
QgsDataItem::State QgsDataItem::state() const
{
// for backward compatibility (if subclass set mPopulated directly)
@ -598,26 +642,15 @@ void QgsDataItem::setState( State state )
if ( state == Populating ) // start loading
{
if ( !mPopulatingMovie )
if ( !mPopulatingIcon )
{
// QApplication as parent to ensure that it is deleted before QApplication
mPopulatingMovie = new QMovie( QApplication::instance() );
mPopulatingMovie->setFileName( QgsApplication::iconPath( "/mIconLoading.gif" ) );
mPopulatingMovie->setCacheMode( QMovie::CacheAll );
connect( mPopulatingMovie, SIGNAL( frameChanged( int ) ), SLOT( setPopulatingIcon() ) );
mPopulatingIcon = new QgsAnimatedIcon( QgsApplication::iconPath( "/mIconLoading.gif" ) );
}
connect( mPopulatingMovie, SIGNAL( frameChanged( int ) ), SLOT( emitDataChanged() ) );
mPopulatingCount++;
mPopulatingMovie->setPaused( false );
mPopulatingIcon->connectFrameChanged( this, SLOT( emitDataChanged() ) );
}
else if ( mState == Populating && mPopulatingMovie ) // stop loading
else if ( mState == Populating && mPopulatingIcon ) // stop loading
{
disconnect( mPopulatingMovie, SIGNAL( frameChanged( int ) ), this, SLOT( emitDataChanged() ) );
mPopulatingCount--;
if ( mPopulatingCount == 0 )
{
mPopulatingMovie->setPaused( true );
}
mPopulatingIcon->disconnectFrameChanged( this, SLOT( emitDataChanged() ) );
}
mState = state;
@ -730,7 +763,7 @@ QgsDirectoryItem::~QgsDirectoryItem()
QIcon QgsDirectoryItem::icon()
{
if ( state() == Populating )
return populatingIcon();
return QgsDataItem::icon();
return iconDir();
}

View File

@ -37,6 +37,38 @@ class QgsDataItem;
typedef QgsDataItem * dataItem_t( QString, QgsDataItem* );
/** Animated icon is keeping an animation running if there are listeners connected to frameChanged */
class QgsAnimatedIcon : public QObject
{
Q_OBJECT
public:
/** Constructor
* @param iconPath path to a movie, e.g. animated GIF */
QgsAnimatedIcon( const QString & iconPath = QString::null );
QString iconPath() const;
void setIconPath( const QString & iconPath );
QIcon icon() const { return mIcon; }
/** Connect listener to frameChanged() signal */
void connectFrameChanged( const QObject * receiver, const char * method );
/** Disconnect listener from frameChanged() signal */
void disconnectFrameChanged( const QObject * receiver, const char * method );
public slots:
void onFrameChanged();
signals:
/** Emited when icon changed */
void frameChanged();
private:
void resetMovie();
int mCount; // number of listeners
QMovie * mMovie;
QIcon mIcon;
};
/** Base class for all items in the model.
* Parent/children hierarchy is not based on QObject. */
@ -172,7 +204,6 @@ class CORE_EXPORT QgsDataItem : public QObject
protected:
virtual void populate( QVector<QgsDataItem*> children );
virtual void refresh( QVector<QgsDataItem*> children );
QIcon populatingIcon() { return mPopulatingIcon; }
/** The item is scheduled to be deleted. E.g. if deleteLater() is called when
* item is in Populating state (createChildren() running in another thread),
* the deferredDelete() returns true and item will be deleted once Populating finished.
@ -225,7 +256,6 @@ class CORE_EXPORT QgsDataItem : public QObject
void emitDataChanged( );
void emitStateChanged( QgsDataItem* item, QgsDataItem::State oldState );
virtual void childrenCreated();
void setPopulatingIcon();
signals:
void beginInsertItems( QgsDataItem* parent, int first, int last );
@ -242,9 +272,7 @@ class CORE_EXPORT QgsDataItem : public QObject
bool mDeferredDelete;
QFutureWatcher< QVector <QgsDataItem*> > *mFutureWatcher;
// number of items currently in loading (populating) state
static int mPopulatingCount;
static QMovie * mPopulatingMovie;
static QIcon mPopulatingIcon;
static QgsAnimatedIcon * mPopulatingIcon;
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsDataItem::Capabilities )