vlc | branch: master | Francois Cartegnie <[email protected]> | Wed Jun 6 19:05:58 2012 +0200| [bd0ae7ec66f9e94b877ec1b206fce52eb133b0ae] | committer: Francois Cartegnie
Qt: PLModel: try to agregate inserts for efficiency > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=bd0ae7ec66f9e94b877ec1b206fce52eb133b0ae --- .../gui/qt4/components/playlist/playlist_model.cpp | 79 ++++++++++++++++++-- .../gui/qt4/components/playlist/playlist_model.hpp | 12 +++ 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/modules/gui/qt4/components/playlist/playlist_model.cpp b/modules/gui/qt4/components/playlist/playlist_model.cpp index 3a9f550..d178d99 100644 --- a/modules/gui/qt4/components/playlist/playlist_model.cpp +++ b/modules/gui/qt4/components/playlist/playlist_model.cpp @@ -48,6 +48,7 @@ #include <QDesktopServices> #include <QInputDialog> #include <QSignalMapper> +#include <QTimer> #define I_NEW_DIR \ I_DIR_OR_FOLDER( N_("Create Directory"), N_( "Create Folder" ) ) @@ -100,6 +101,7 @@ PLModel::PLModel( playlist_t *_p_playlist, /* THEPL */ this, processItemAppend( int, int ) ); CONNECT( THEMIM, playlistItemRemoved( int ), this, processItemRemoval( int ) ); + CONNECT( &insertBufferCommitTimer, timeout(), this, commitBufferedRowInserts() ); } PLModel::~PLModel() @@ -628,6 +630,68 @@ void PLModel::processItemRemoval( int i_id ) removeItem( i_id ); } +void PLModel::commitBufferedRowInserts() +{ + PLItem *toemit = NULL; + insertBufferCommitTimer.stop(); + insertBufferMutex.lock(); + if ( !insertBuffer.isEmpty() ) + { + beginInsertRows( index( insertBufferRoot, 0 ), insertbuffer_firstrow, insertbuffer_lastrow ); + foreach (PLItem *item, insertBuffer) + { + insertBufferRoot->insertChild( item, insertbuffer_firstrow++ ); + if( item->inputItem() == THEMIM->currentInputItem() ) + toemit = item; + } + endInsertRows(); + insertBuffer.clear(); + } + insertBufferMutex.unlock(); + if ( toemit ) + emit currentIndexChanged( index( toemit, 0 ) ); +} + +/* + Tries to agregate linear inserts of single row. Sends + more efficient updates notifications to views and then + avoids the flickering effect. +*/ +void PLModel::bufferedRowInsert( PLItem *item, PLItem *parent, int pos ) +{ + insertBufferMutex.lock(); + if ( ! insertBuffer.isEmpty() ) + { + /* Check if we're doing linear insert */ + if ( parent != insertBufferRoot || pos != insertbuffer_lastrow + 1 ) + { + insertBufferMutex.unlock(); + commitBufferedRowInserts(); + bufferedRowInsert( item, parent, pos ); + return; + } + } + + if ( insertBuffer.isEmpty() ) + { + insertBuffer << item; + insertBufferRoot = parent; + insertbuffer_firstrow = pos; + insertbuffer_lastrow = pos; + } else { + insertBuffer << item; + insertbuffer_lastrow++; + } + insertBufferMutex.unlock(); + + /* Schedule commit */ + if ( ! insertBufferCommitTimer.isActive() ) + { + insertBufferCommitTimer.setSingleShot( true ); + insertBufferCommitTimer.start( 100 ); + } +} + void PLModel::processItemAppend( int i_item, int i_parent ) { playlist_item_t *p_item = NULL; @@ -657,12 +721,7 @@ void PLModel::processItemAppend( int i_item, int i_parent ) PL_UNLOCK; /* We insert the newItem (children) inside the parent */ - beginInsertRows( index( nodeParentItem, 0 ), pos, pos ); - nodeParentItem->insertChild( newItem, pos ); - endInsertRows(); - - if( newItem->inputItem() == THEMIM->currentInputItem() ) - emit currentIndexChanged( index( newItem, 0 ) ); + bufferedRowInsert( newItem, nodeParentItem, pos ); if( latestSearch.isEmpty() ) return; search( latestSearch, index( rootItem, 0), false /*FIXME*/ ); @@ -693,6 +752,7 @@ void PLModel::rebuild( playlist_item_t *p_root ) void PLModel::takeItem( PLItem *item ) { + commitBufferedRowInserts(); assert( item ); PLItem *parent = item->parent(); assert( parent ); @@ -705,6 +765,7 @@ void PLModel::takeItem( PLItem *item ) void PLModel::insertChildren( PLItem *node, QList<PLItem*>& items, int i_pos ) { + commitBufferedRowInserts(); assert( node ); int count = items.count(); if( !count ) return; @@ -720,6 +781,7 @@ void PLModel::insertChildren( PLItem *node, QList<PLItem*>& items, int i_pos ) void PLModel::removeItem( PLItem *item ) { if( !item ) return; + commitBufferedRowInserts(); i_cached_id = -1; i_cached_input_id = -1; @@ -822,6 +884,9 @@ void PLModel::sort( const int i_root_id, const int column, Qt::SortOrder order ) PLItem *item = findById( rootItem, i_root_id ); if( !item ) return; + + commitBufferedRowInserts(); + QModelIndex qIndex = index( item, 0 ); int count = item->childCount(); if( count ) @@ -868,6 +933,8 @@ void PLModel::search( const QString& search_text, const QModelIndex & idx, bool { latestSearch = search_text; + commitBufferedRowInserts(); + /** \todo Fire the search with a small delay ? */ PL_LOCK; { diff --git a/modules/gui/qt4/components/playlist/playlist_model.hpp b/modules/gui/qt4/components/playlist/playlist_model.hpp index 133928f..9eee44f 100644 --- a/modules/gui/qt4/components/playlist/playlist_model.hpp +++ b/modules/gui/qt4/components/playlist/playlist_model.hpp @@ -41,6 +41,8 @@ #include <QAbstractItemModel> #include <QVariant> #include <QModelIndex> +#include <QTimer> +#include <QMutex> class PLItem; class PLSelector; @@ -130,6 +132,15 @@ private: static QIcon icons[ITEM_TYPE_NUMBER]; + /* single row linear inserts agregation */ + void bufferedRowInsert( PLItem *item, PLItem *parent, int pos ); + PLItem *insertBufferRoot; + int insertbuffer_firstrow; + int insertbuffer_lastrow; + QTimer insertBufferCommitTimer; + QList<PLItem *> insertBuffer; + QMutex insertBufferMutex; + /* Custom model private methods */ /* Lookups */ QStringList selectedURIs(); @@ -192,6 +203,7 @@ private slots: void processInputItemUpdate( input_thread_t* p_input ); void processItemRemoval( int i_id ); void processItemAppend( int item, int parent ); + void commitBufferedRowInserts(); void activateItem( playlist_item_t *p_item ); void increaseZoom(); void decreaseZoom(); _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
