ResourceModel: implement filter functionality

So far all subclasses implemented filtering on their own which doesn't
make much sense. Now one can set filter keywords and a filter type for
all ResourceModels. Subclasses simply have to call
ResourceModel::itemMatchesFilter( ResourceItem ) in order to determine
whether an item should be hidden or not. Additionally they have to
implement the updateFilters() method in order to update their internal
management data each time the filters change.
This commit is contained in:
Tobias Doerffel
2009-08-21 16:49:27 +02:00
parent 36ec30f649
commit d3bb3ff13a
9 changed files with 80 additions and 61 deletions

View File

@@ -213,7 +213,7 @@ public:
void reload();
// returns true if all given keywords match name, tags etc.
bool keywordMatch( const QStringList & _keywords );
bool keywordMatch( const QStringList & _keywords ) const;
// return true, if given ResourceItem is equal
bool operator==( const ResourceItem & _other ) const;

View File

@@ -1,5 +1,5 @@
/*
* ResourceListModel.h - a tree model implementation for resources
* ResourceListModel.h - a list model implementation for resources
*
* Copyright (c) 2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -32,14 +32,13 @@
class ResourceListModel : public ResourceModel
{
Q_OBJECT
public:
ResourceListModel( ResourceDB * _db, QObject * _parent = NULL );
virtual ~ResourceListModel()
{
}
int rowCount( const QModelIndex & _parent = QModelIndex() ) const;
virtual int rowCount( const QModelIndex & _parent = QModelIndex() ) const;
virtual QModelIndex index( int _row, int _col,
const QModelIndex & _parent = QModelIndex() ) const;
@@ -49,15 +48,10 @@ public:
return QModelIndex();
}
virtual void setFilter( const QString & _s );
private slots:
void updateLookupTable();
virtual void updateFilters();
private:
QStringList m_filterKeywords;
QVector<ResourceItem *> m_lookupTable;
} ;

View File

@@ -27,6 +27,7 @@
#include <QtCore/QAbstractItemModel>
#include "lmms_basics.h"
#include "ResourceDB.h"
@@ -70,12 +71,32 @@ public:
int totalItems() const;
int shownItems() const;
QStringList keywordFilter() const
{
return m_keywordFilter;
}
ResourceItem::Type typeFilter() const
{
return m_typeFilter;
}
public slots:
virtual void setFilter( const QString & _s ) = 0;
virtual void updateFilters() = 0;
void setKeywordFilter( const QString & _keywords );
void setTypeFilter( ResourceItem::Type _type = ResourceItem::TypeUnknown );
protected:
inline bool itemMatchesFilter( const ResourceItem & _item ) const
{
return ( likely( typeFilter() == ResourceItem::TypeUnknown ) ||
typeFilter() == _item.type() ) &&
( likely( m_keywordFilterSet == false ) ||
_item.keywordMatch( keywordFilter() ) );
}
ResourceDB * db() const
{
return m_db;
@@ -84,6 +105,9 @@ protected:
private:
ResourceDB * m_db;
QStringList m_keywordFilter;
bool m_keywordFilterSet;
ResourceItem::Type m_typeFilter;
signals:

View File

@@ -36,20 +36,19 @@ public:
{
}
int rowCount( const QModelIndex & _parent = QModelIndex() ) const;
virtual int rowCount( const QModelIndex & _parent = QModelIndex() ) const;
virtual QModelIndex index( int _row, int _col,
const QModelIndex & _parent = QModelIndex() ) const;
virtual QModelIndex parent( const QModelIndex & _index ) const;
virtual void setFilter( const QString & _s );
virtual void updateFilters();
private:
bool filterItems( ResourceItem::Relation * _item,
const QModelIndex & _parent,
const QStringList & _keywords );
const QModelIndex & _parent );
void setHidden( ResourceItem::Relation * _item,
const QModelIndex & _parent,
bool _hidden,

View File

@@ -94,7 +94,7 @@ void ResourceItem::reload()
bool ResourceItem::keywordMatch( const QStringList & _keywords )
bool ResourceItem::keywordMatch( const QStringList & _keywords ) const
{
for( QStringList::ConstIterator it = _keywords.begin();
it != _keywords.end(); ++it )

View File

@@ -29,11 +29,7 @@ ResourceListModel::ResourceListModel( ResourceDB * _db, QObject * _parent ) :
ResourceModel( _db, _parent ),
m_lookupTable()
{
connect( db(), SIGNAL( itemsChanged() ),
this, SLOT( updateLookupTable() ),
Qt::DirectConnection );
updateLookupTable();
updateFilters();
}
@@ -63,27 +59,12 @@ QModelIndex ResourceListModel::index( int _row, int _col,
void ResourceListModel::setFilter( const QString & _s )
{
if( !_s.isEmpty() )
{
m_filterKeywords = _s.toLower().split( " " );
}
else
{
m_filterKeywords.clear();
}
updateLookupTable();
}
// update lookup table so ResourceListModel::index(...) can run with O(1)
void ResourceListModel::updateLookupTable()
void ResourceListModel::updateFilters()
{
// update lookup table so ResourceListModel::index(...) can run with O(1)
int items = 0;
if( m_filterKeywords.isEmpty() )
if( keywordFilter().isEmpty() &&
typeFilter() == ResourceItem::TypeUnknown )
{
// unhide all items if empty filter string given
m_lookupTable.resize( db()->items().size() );
@@ -99,7 +80,7 @@ void ResourceListModel::updateLookupTable()
// filter and count number of non-hidden items
foreach( ResourceItem * item, db()->items() )
{
if( item->keywordMatch( m_filterKeywords ) )
if( itemMatchesFilter( *item ) )
{
item->setHidden( false, this );
++items;
@@ -131,7 +112,4 @@ void ResourceListModel::updateLookupTable()
}
#include "moc_ResourceListModel.cxx"
/* vim: set tw=0 noexpandtab: */

View File

@@ -32,12 +32,18 @@
ResourceModel::ResourceModel( ResourceDB * _db, QObject * _parent ) :
QAbstractItemModel( _parent ),
m_db( _db )
m_db( _db ),
m_keywordFilter(),
m_keywordFilterSet( false ),
m_typeFilter( ResourceItem::TypeUnknown )
{
setSupportedDragActions( Qt::CopyAction );
connect( db(), SIGNAL( itemsChanged() ),
this, SIGNAL( itemsChanged() ) );
this, SIGNAL( itemsChanged() ) );
connect( db(), SIGNAL( itemsChanged() ),
this, SLOT( updateFilters() ),
Qt::DirectConnection );
}
@@ -249,6 +255,29 @@ int ResourceModel::shownItems() const
void ResourceModel::setKeywordFilter( const QString & _keywords )
{
if( !_keywords.isEmpty() )
{
m_keywordFilter = _keywords.toLower().split( " " );
m_keywordFilterSet = true;
}
else
{
m_keywordFilter.clear();
m_keywordFilterSet = false;
}
updateFilters();
}
void ResourceModel::setTypeFilter( ResourceItem::Type _type )
{
m_typeFilter = _type;
updateFilters();
}

View File

@@ -104,12 +104,11 @@ QModelIndex ResourceTreeModel::parent( const QModelIndex & _idx ) const
void ResourceTreeModel::setFilter( const QString & _s )
void ResourceTreeModel::updateFilters()
{
filterItems( db()->topLevelNode(),
createIndex( 0, 0, db()->topLevelNode() ),
_s.toLower().split( " " ) );
if( _s.isEmpty() )
createIndex( 0, 0, db()->topLevelNode() ) );
if( keywordFilter().isEmpty() )
{
emit layoutChanged();
}
@@ -119,16 +118,12 @@ void ResourceTreeModel::setFilter( const QString & _s )
bool ResourceTreeModel::filterItems( ResourceItem::Relation * _item,
const QModelIndex & _parent,
const QStringList & _keywords )
const QModelIndex & _parent )
{
if( _item->item() )
if( _item->item() && itemMatchesFilter( *( _item->item() ) ) )
{
if( _item->item()->keywordMatch( _keywords ) )
{
setHidden( _item, _parent, false );
return true;
}
setHidden( _item, _parent, false );
return true;
}
int row = 0;
@@ -136,7 +131,7 @@ bool ResourceTreeModel::filterItems( ResourceItem::Relation * _item,
foreachResourceItemRelation( _item->children() )
{
QModelIndex idx = createIndex( row, 0, *it );
if( filterItems( *it, idx, _keywords ) )
if( filterItems( *it, idx ) )
{
hide = false;
}

View File

@@ -48,11 +48,11 @@ void ResourceTreeView::setFilter( const QString & _s )
if( _s.isEmpty() )
{
collapseAll();
m_tm->setFilter( _s );
m_tm->setKeywordFilter( _s );
}
else
{
m_tm->setFilter( _s );
m_tm->setKeywordFilter( _s );
expandToDepth( _s.size() );
}
setUpdatesEnabled( true );