Skip to content
Permalink
Browse files

new class QgsAnimatedIcon

  • Loading branch information
blazek committed May 26, 2015
1 parent 72c9830 commit 0c4ea1f6e550119c46f5726f713f7358e4c4e598
Showing with 93 additions and 33 deletions.
  1. +0 −1 python/core/qgsdataitem.sip
  2. +60 −27 src/core/qgsdataitem.cpp
  3. +33 −5 src/core/qgsdataitem.h
@@ -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 );
@@ -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();
}

@@ -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 )

0 comments on commit 0c4ea1f

Please sign in to comment.