2015-05-28 23:08:29 +05:30
# include "ResourceProxyModel.h"
# include <QItemSelectionRange>
# include "Resource.h"
# include "ResourceObserver.h"
class ModelResourceObserver : public ResourceObserver
{
public :
explicit ModelResourceObserver ( const QModelIndex & index , const int role )
: m_index ( index ) , m_role ( role )
{
qRegisterMetaType < QVector < int > > ( " QVector<int> " ) ;
}
void resourceUpdated ( ) override
{
if ( m_index . isValid ( ) )
{
2015-06-06 16:00:49 +05:30
// the resource changed, pretend to be the model and notify the views of the update. they will re-poll the model which will return the new resource value
2015-05-28 23:08:29 +05:30
QMetaObject : : invokeMethod ( const_cast < QAbstractItemModel * > ( m_index . model ( ) ) ,
" dataChanged " , Qt : : QueuedConnection ,
Q_ARG ( QModelIndex , m_index ) , Q_ARG ( QModelIndex , m_index ) , Q_ARG ( QVector < int > , QVector < int > ( ) < < m_role ) ) ;
}
}
private :
QPersistentModelIndex m_index ;
int m_role ;
} ;
ResourceProxyModel : : ResourceProxyModel ( const int resultTypeId , QObject * parent )
: QIdentityProxyModel ( parent ) , m_resultTypeId ( resultTypeId )
{
}
QVariant ResourceProxyModel : : data ( const QModelIndex & proxyIndex , int role ) const
{
const QModelIndex mapped = mapToSource ( proxyIndex ) ;
2015-06-06 16:00:49 +05:30
// valid cell that's a Qt::DecorationRole and that contains a non-empty string
2015-05-28 23:08:29 +05:30
if ( mapped . isValid ( ) & & role = = Qt : : DecorationRole & & ! mapToSource ( proxyIndex ) . data ( role ) . toString ( ) . isEmpty ( ) )
{
2015-06-06 16:00:49 +05:30
// do we already have a resource for this index?
2015-05-28 23:08:29 +05:30
if ( ! m_resources . contains ( mapped ) )
{
2015-06-06 16:00:49 +05:30
Resource : : Ptr placeholder ;
const QVariant placeholderIdentifier = mapped . data ( PlaceholderRole ) ;
if ( ! placeholderIdentifier . isNull ( ) & & placeholderIdentifier . type ( ) = = QVariant : : String )
2015-05-28 23:08:29 +05:30
{
2015-06-06 16:00:49 +05:30
placeholder = Resource : : create ( placeholderIdentifier . toString ( ) ) ;
2015-05-28 23:08:29 +05:30
}
2015-06-06 16:00:49 +05:30
// create the Resource and apply the observer for models
Resource : : Ptr res = Resource : : create ( mapToSource ( proxyIndex ) . data ( role ) . toString ( ) , placeholder )
- > applyTo ( new ModelResourceObserver ( proxyIndex , role ) ) ;
2015-05-28 23:08:29 +05:30
m_resources . insert ( mapped , res ) ;
}
return m_resources . value ( mapped ) - > getResourceInternal ( m_resultTypeId ) ;
}
2015-06-06 16:00:49 +05:30
// otherwise fall back to the source model
2015-05-28 23:08:29 +05:30
return mapped . data ( role ) ;
}
void ResourceProxyModel : : setSourceModel ( QAbstractItemModel * model )
{
if ( sourceModel ( ) )
{
disconnect ( sourceModel ( ) , 0 , this , 0 ) ;
}
if ( model )
{
connect ( model , & QAbstractItemModel : : dataChanged , this , [ this ] ( const QModelIndex & tl , const QModelIndex & br , const QVector < int > & roles )
{
2015-06-06 16:00:49 +05:30
// invalidate resources so that they will be re-created
if ( roles . contains ( Qt : : DecorationRole ) | | roles . contains ( PlaceholderRole ) | | roles . isEmpty ( ) )
2015-05-28 23:08:29 +05:30
{
const QItemSelectionRange range ( tl , br ) ;
for ( const QModelIndex & index : range . indexes ( ) )
{
m_resources . remove ( index ) ;
}
}
} ) ;
}
QIdentityProxyModel : : setSourceModel ( model ) ;
}