From d3bb3ff13af7a1ac1a8e12e1278e433ba494fd4b Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Fri, 21 Aug 2009 16:49:27 +0200 Subject: [PATCH] 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. --- include/ResourceItem.h | 2 +- include/ResourceListModel.h | 12 +++--------- include/ResourceModel.h | 26 +++++++++++++++++++++++++- include/ResourceTreeModel.h | 7 +++---- src/core/ResourceItem.cpp | 2 +- src/core/ResourceListModel.cpp | 34 ++++++---------------------------- src/core/ResourceModel.cpp | 33 +++++++++++++++++++++++++++++++-- src/core/ResourceTreeModel.cpp | 21 ++++++++------------- src/gui/ResourceTreeView.cpp | 4 ++-- 9 files changed, 80 insertions(+), 61 deletions(-) diff --git a/include/ResourceItem.h b/include/ResourceItem.h index f2b645b00..139694c33 100644 --- a/include/ResourceItem.h +++ b/include/ResourceItem.h @@ -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; diff --git a/include/ResourceListModel.h b/include/ResourceListModel.h index df7914c8e..bcf9ed9d9 100644 --- a/include/ResourceListModel.h +++ b/include/ResourceListModel.h @@ -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 * @@ -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 m_lookupTable; } ; diff --git a/include/ResourceModel.h b/include/ResourceModel.h index 4368af15f..a6ed4a3ac 100644 --- a/include/ResourceModel.h +++ b/include/ResourceModel.h @@ -27,6 +27,7 @@ #include +#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: diff --git a/include/ResourceTreeModel.h b/include/ResourceTreeModel.h index 91c2487d3..7d546acf4 100644 --- a/include/ResourceTreeModel.h +++ b/include/ResourceTreeModel.h @@ -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, diff --git a/src/core/ResourceItem.cpp b/src/core/ResourceItem.cpp index 7e871aa83..09ac45121 100644 --- a/src/core/ResourceItem.cpp +++ b/src/core/ResourceItem.cpp @@ -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 ) diff --git a/src/core/ResourceListModel.cpp b/src/core/ResourceListModel.cpp index 0c547664f..66649c6c1 100644 --- a/src/core/ResourceListModel.cpp +++ b/src/core/ResourceListModel.cpp @@ -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: */ diff --git a/src/core/ResourceModel.cpp b/src/core/ResourceModel.cpp index 960da239b..9cc0368cd 100644 --- a/src/core/ResourceModel.cpp +++ b/src/core/ResourceModel.cpp @@ -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(); +} diff --git a/src/core/ResourceTreeModel.cpp b/src/core/ResourceTreeModel.cpp index 564f1b2aa..c18360051 100644 --- a/src/core/ResourceTreeModel.cpp +++ b/src/core/ResourceTreeModel.cpp @@ -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; } diff --git a/src/gui/ResourceTreeView.cpp b/src/gui/ResourceTreeView.cpp index 157860cbb..91dbe9577 100644 --- a/src/gui/ResourceTreeView.cpp +++ b/src/gui/ResourceTreeView.cpp @@ -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 );