mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
new class QgsAnimatedIcon
This commit is contained in:
parent
72c9830178
commit
0c4ea1f6e5
@ -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 )
|
||||
|
Loading…
x
Reference in New Issue
Block a user