#include <QDesktopServices>
#include <QInputDialog>
#include <QSignalMapper>
+#include <QTimer>
#define I_NEW_DIR \
I_DIR_OR_FOLDER( N_("Create Directory"), N_( "Create Folder" ) )
this, processItemAppend( int, int ) );
CONNECT( THEMIM, playlistItemRemoved( int ),
this, processItemRemoval( int ) );
+ CONNECT( &insertBufferCommitTimer, timeout(), this, commitBufferedRowInserts() );
}
PLModel::~PLModel()
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;
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*/ );
void PLModel::takeItem( PLItem *item )
{
+ commitBufferedRowInserts();
assert( item );
PLItem *parent = item->parent();
assert( parent );
void PLModel::insertChildren( PLItem *node, QList<PLItem*>& items, int i_pos )
{
+ commitBufferedRowInserts();
assert( node );
int count = items.count();
if( !count ) return;
void PLModel::removeItem( PLItem *item )
{
if( !item ) return;
+ commitBufferedRowInserts();
i_cached_id = -1;
i_cached_input_id = -1;
PLItem *item = findById( rootItem, i_root_id );
if( !item ) return;
+
+ commitBufferedRowInserts();
+
QModelIndex qIndex = index( item, 0 );
int count = item->childCount();
if( count )
{
latestSearch = search_text;
+ commitBufferedRowInserts();
+
/** \todo Fire the search with a small delay ? */
PL_LOCK;
{
#include <QAbstractItemModel>
#include <QVariant>
#include <QModelIndex>
+#include <QTimer>
+#include <QMutex>
class PLItem;
class PLSelector;
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();
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();