From f85e34a3e99038d3fd2c939f3bf7355f4f2df4a3 Mon Sep 17 00:00:00 2001 From: "Uwe L. Korn" Date: Sun, 12 Oct 2014 11:29:44 +0100 Subject: [PATCH] Memoize visibility filter --- .../playlist/PlayableProxyModel.cpp | 30 ++++++++++++------- src/libtomahawk/playlist/PlayableProxyModel.h | 20 +++++++++++-- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/libtomahawk/playlist/PlayableProxyModel.cpp b/src/libtomahawk/playlist/PlayableProxyModel.cpp index 88d521d86..e58aafc00 100644 --- a/src/libtomahawk/playlist/PlayableProxyModel.cpp +++ b/src/libtomahawk/playlist/PlayableProxyModel.cpp @@ -145,20 +145,22 @@ PlayableProxyModel::setSourcePlayableModel( PlayableModel* sourceModel ) bool PlayableProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const { + PlayableProxyModelFilterMemo memo; + PlayableItem* pi = itemFromIndex( sourceModel()->index( sourceRow, 0, sourceParent ) ); if ( !pi ) return false; - return filterAcceptsRowInternal( sourceRow, pi, sourceParent ); + return filterAcceptsRowInternal( sourceRow, pi, sourceParent, memo ); } bool -PlayableProxyModel::filterAcceptsRowInternal( int sourceRow, PlayableItem* pi, const QModelIndex& sourceParent ) const +PlayableProxyModel::filterAcceptsRowInternal( int sourceRow, PlayableItem* pi, const QModelIndex& sourceParent, PlayableProxyModelFilterMemo& memo ) const { - if ( m_maxVisibleItems > 0 && !visibilityFilterAcceptsRow( sourceRow, sourceParent ) ) + if ( m_maxVisibleItems > 0 && !visibilityFilterAcceptsRow( sourceRow, sourceParent, memo ) ) return false; - if ( m_hideDupeItems && !dupeFilterAcceptsRow( sourceRow, pi, sourceParent ) ) + if ( m_hideDupeItems && !dupeFilterAcceptsRow( sourceRow, pi, sourceParent, memo ) ) return false; return nameFilterAcceptsRow( sourceRow, pi, sourceParent ); @@ -166,7 +168,7 @@ PlayableProxyModel::filterAcceptsRowInternal( int sourceRow, PlayableItem* pi, c bool -PlayableProxyModel::dupeFilterAcceptsRow( int sourceRow, PlayableItem* pi, const QModelIndex& sourceParent ) const +PlayableProxyModel::dupeFilterAcceptsRow( int sourceRow, PlayableItem* pi, const QModelIndex& sourceParent, PlayableProxyModelFilterMemo& memo ) const { if ( !m_hideDupeItems ) return true; @@ -181,7 +183,7 @@ PlayableProxyModel::dupeFilterAcceptsRow( int sourceRow, PlayableItem* pi, const ( pi->album() && pi->album() == di->album() ) || ( pi->artist() && pi->artist()->name() == di->artist()->name() ); - if ( b && filterAcceptsRowInternal( i, di, sourceParent ) ) + if ( b && filterAcceptsRowInternal( i, di, sourceParent, memo ) ) return false; } @@ -190,18 +192,26 @@ PlayableProxyModel::dupeFilterAcceptsRow( int sourceRow, PlayableItem* pi, const bool -PlayableProxyModel::visibilityFilterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const +PlayableProxyModel::visibilityFilterAcceptsRow( int sourceRow, const QModelIndex& sourceParent, PlayableProxyModelFilterMemo& memo ) const { if ( m_maxVisibleItems <= 0 ) return true; - int items = 0; - for ( int i = 0; ( i < sourceRow ) && ( items < m_maxVisibleItems ) ; i++ ) + if ( static_cast( sourceRow ) < memo.visibilty.size() ) + { + // We have already memoized the return value. + return memo.visibilty[sourceRow] < m_maxVisibleItems; + } + + int items = memo.visibilty.back(); + for ( int i = memo.visibilty.size() - 1; ( i < sourceRow ) && ( items < m_maxVisibleItems ) ; i++ ) { PlayableItem* pi = itemFromIndex( sourceModel()->index( i, 0, sourceParent ) ); - if ( pi && dupeFilterAcceptsRow( i, pi, sourceParent ) && nameFilterAcceptsRow( i, pi, sourceParent ) ) + // We will not change memo in these calls as all values needed in them are already memoized. + if ( pi && dupeFilterAcceptsRow( i, pi, sourceParent, memo ) && nameFilterAcceptsRow( i, pi, sourceParent ) ) { items++; + memo.visibilty.push_back( items ); // Sets memo.visibilty[i + 1] to items } } diff --git a/src/libtomahawk/playlist/PlayableProxyModel.h b/src/libtomahawk/playlist/PlayableProxyModel.h index 9adc0aa93..86a92dceb 100644 --- a/src/libtomahawk/playlist/PlayableProxyModel.h +++ b/src/libtomahawk/playlist/PlayableProxyModel.h @@ -27,6 +27,20 @@ #include "DllMacro.h" +class PlayableProxyModelFilterMemo +{ +public: + PlayableProxyModelFilterMemo() + { + // First element always has no predecessors. + // TODO C++11: Make this a constexpr using initializer lists. + visibilty.push_back( 0 ); + } + + virtual ~PlayableProxyModelFilterMemo() {} + std::vector visibilty; +}; + class DLLEXPORT PlayableProxyModel : public QSortFilterProxyModel { Q_OBJECT @@ -117,10 +131,10 @@ private slots: void onCurrentIndexChanged( const QModelIndex& newIndex, const QModelIndex& oldIndex ); private: - bool filterAcceptsRowInternal( int sourceRow, PlayableItem* pi, const QModelIndex& sourceParent ) const; + bool filterAcceptsRowInternal( int sourceRow, PlayableItem* pi, const QModelIndex& sourceParent, PlayableProxyModelFilterMemo& memo ) const; bool nameFilterAcceptsRow( int sourceRow, PlayableItem* pi, const QModelIndex& sourceParent ) const; - bool dupeFilterAcceptsRow( int sourceRow, PlayableItem* pi, const QModelIndex& sourceParent ) const; - bool visibilityFilterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const; + bool dupeFilterAcceptsRow( int sourceRow, PlayableItem* pi, const QModelIndex& sourceParent, PlayableProxyModelFilterMemo& memo ) const; + bool visibilityFilterAcceptsRow( int sourceRow, const QModelIndex& sourceParent, PlayableProxyModelFilterMemo& memo ) const; bool lessThan( int column, const Tomahawk::query_ptr& left, const Tomahawk::query_ptr& right ) const; PlayableModel* m_model;