Commit 0b3ef518 authored by Jakob Leben's avatar Jakob Leben

qt4 playlist: don't rebuild on move (finally!) + refresh current item on sort

When using tree playlist mode and moving items within sub-nodes, the nodes
will now stay open.
parent 883694a2
...@@ -84,6 +84,25 @@ void PLItem::insertChild( PLItem *item, int i_pos, bool signal ) ...@@ -84,6 +84,25 @@ void PLItem::insertChild( PLItem *item, int i_pos, bool signal )
children.insert( i_pos, item ); children.insert( i_pos, item );
} }
void PLItem::removeChild( PLItem *item )
{
children.removeOne( item );
delete item;
}
void PLItem::removeChildren()
{
qDeleteAll( children );
children.clear();
}
void PLItem::takeChildAt( int index )
{
PLItem *child = children[index];
child->parentItem = NULL;
children.removeAt( index );
}
/* This function is used to get one's parent's row number in the model */ /* This function is used to get one's parent's row number in the model */
int PLItem::row() const int PLItem::row() const
{ {
......
...@@ -46,6 +46,9 @@ public: ...@@ -46,6 +46,9 @@ public:
{ {
children.insert( children.count(), item ); children.insert( children.count(), item );
}; };
void removeChild( PLItem * );
void removeChildren();
void takeChildAt( int );
PLItem *child( int row ) { return children.value( row ); }; PLItem *child( int row ) { return children.value( row ); };
int childCount() const { return children.count(); }; int childCount() const { return children.count(); };
......
...@@ -163,11 +163,10 @@ Qt::ItemFlags PLModel::flags( const QModelIndex &index ) const ...@@ -163,11 +163,10 @@ Qt::ItemFlags PLModel::flags( const QModelIndex &index ) const
return flags; return flags;
} }
/* A list of model indexes are a playlist */
QStringList PLModel::mimeTypes() const QStringList PLModel::mimeTypes() const
{ {
QStringList types; QStringList types;
types << "vlc/playlist-item-id"; types << "vlc/qt-playlist-item";
return types; return types;
} }
...@@ -186,9 +185,10 @@ QMimeData *PLModel::mimeData( const QModelIndexList &indexes ) const ...@@ -186,9 +185,10 @@ QMimeData *PLModel::mimeData( const QModelIndexList &indexes ) const
qSort(list); qSort(list);
foreach( const QModelIndex &index, list ) { foreach( const QModelIndex &index, list ) {
stream << itemId( index ); PLItem *item = getItem( index );
stream.writeRawData( (char*) &item, sizeof( PLItem* ) );
} }
mimeData->setData( "vlc/playlist-item-id", encodedData ); mimeData->setData( "vlc/qt-playlist-item", encodedData );
return mimeData; return mimeData;
} }
...@@ -196,28 +196,16 @@ QMimeData *PLModel::mimeData( const QModelIndexList &indexes ) const ...@@ -196,28 +196,16 @@ QMimeData *PLModel::mimeData( const QModelIndexList &indexes ) const
bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action, bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent ) int row, int column, const QModelIndex &parent )
{ {
if( data->hasFormat( "vlc/playlist-item-id" ) ) if( data->hasFormat( "vlc/qt-playlist-item" ) )
{ {
if( action == Qt::IgnoreAction ) if( action == Qt::IgnoreAction )
return true; return true;
PL_LOCK; PLItem *parentItem = parent.isValid() ? getItem( parent ) : rootItem;
playlist_item_t *p_parent;
if( !parent.isValid())
{
if( row > -1)
p_parent = playlist_ItemGetById( p_playlist, rootItem->i_id );
else
{
PL_UNLOCK;
return true;
}
}
else
p_parent = playlist_ItemGetById( p_playlist, itemId ( parent ) );
PL_LOCK;
playlist_item_t *p_parent =
playlist_ItemGetById( p_playlist, parentItem->i_id );
if( !p_parent || p_parent->i_children == -1 ) if( !p_parent || p_parent->i_children == -1 )
{ {
PL_UNLOCK; PL_UNLOCK;
...@@ -225,72 +213,104 @@ bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action, ...@@ -225,72 +213,104 @@ bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action,
} }
bool copy = false; bool copy = false;
if( row == -1 && playlist_item_t *p_pl = p_playlist->p_local_category;
( p_parent->p_input == p_playlist->p_local_category->p_input playlist_item_t *p_ml = p_playlist->p_ml_category;
|| p_parent->p_input == p_playlist->p_ml_category->p_input ) ) if
copy = true; (
row == -1 && (
QByteArray encodedData = data->data( "vlc/playlist-item-id" ); ( p_pl && p_parent->p_input == p_pl->p_input ) ||
QDataStream stream( &encodedData, QIODevice::ReadOnly ); ( p_ml && p_parent->p_input == p_ml->p_input ) )
)
copy = true;
PL_UNLOCK;
QByteArray encodedData = data->data( "vlc/qt-playlist-item" );
if( copy ) if( copy )
dropAppendCopy( encodedData, parentItem );
else
dropMove( encodedData, parentItem, row );
}
return true;
}
void PLModel::dropAppendCopy( QByteArray& data, PLItem *target )
{
QDataStream stream( &data, QIODevice::ReadOnly );
PL_LOCK;
playlist_item_t *p_parent =
playlist_ItemGetById( p_playlist, target->i_id );
while( !stream.atEnd() )
{
PLItem *item;
stream.readRawData( (char*)&item, sizeof(PLItem*) );
playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id );
if( !p_item ) continue;
input_item_t *p_input = p_item->p_input;
playlist_AddExt ( p_playlist,
p_input->psz_uri, p_input->psz_name,
PLAYLIST_APPEND | PLAYLIST_SPREPARSE, PLAYLIST_END,
p_input->i_duration,
p_input->i_options, p_input->ppsz_options, p_input->optflagc,
p_parent == p_playlist->p_local_category, true );
}
PL_UNLOCK;
}
void PLModel::dropMove( QByteArray& data, PLItem *target, int row )
{
QDataStream stream( &data, QIODevice::ReadOnly );
QList<PLItem*> model_items;
QList<int> ids;
int new_pos = row == -1 ? target->children.size() : row;
int model_pos = new_pos;
while( !stream.atEnd() )
{
PLItem *item;
stream.readRawData( (char*)&item, sizeof(PLItem*) );
/* better not try to move a node into itself: */
PLItem *climber = target;
while( climber )
{ {
while( !stream.atEnd() ) if( climber == item ) break;
{ climber = climber->parentItem;
int i_id;
stream >> i_id;
playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id );
if( !p_item )
{
PL_UNLOCK;
return false;
}
input_item_t *p_input = p_item->p_input;
playlist_AddExt ( p_playlist,
p_input->psz_uri, p_input->psz_name,
PLAYLIST_APPEND | PLAYLIST_SPREPARSE, PLAYLIST_END,
p_input->i_duration,
p_input->i_options, p_input->ppsz_options, p_input->optflagc,
p_parent == p_playlist->p_local_category, true );
}
} }
else if( climber ) continue;
if( item->parentItem == target &&
target->children.indexOf( item ) < model_pos )
model_pos--;
ids.append( item->i_id );
model_items.append( item );
TakeItem( item );
}
int count = ids.size();
if( count )
{
playlist_item_t *pp_items[count];
PL_LOCK;
for( int i = 0; i < count; i++ )
{ {
QList<playlist_item_t*> items; playlist_item_t *p_item = playlist_ItemGetById( p_playlist, ids[i] );
while( !stream.atEnd() ) if( !p_item )
{
int id;
stream >> id;
playlist_item_t *item = playlist_ItemGetById( p_playlist, id );
if( !item ) continue;
/* better not try to move a node into itself: */
if( item->i_children > 0 )
{
playlist_item_t *climber = p_parent;
while( climber )
{
if( climber == item ) break;
climber = climber->p_parent;
}
if( climber ) continue;
}
items.append( item );
}
int count = items.size();
if( count )
{ {
playlist_item_t *pp_items[count]; PL_UNLOCK;
for( int i = 0; i < count; i++ ) pp_items[i] = items[i]; return;
playlist_TreeMoveMany( p_playlist, count, pp_items, p_parent,
(row == -1 ? p_parent->i_children : row) );
} }
pp_items[i] = p_item;
} }
playlist_item_t *p_parent =
playlist_ItemGetById( p_playlist, target->i_id );
playlist_TreeMoveMany( p_playlist, count, pp_items, p_parent,
new_pos );
PL_UNLOCK; PL_UNLOCK;
/*TODO: That's not a good idea to rebuild the playlist */
rebuild(); InsertChildren( target, model_items, model_pos );
} }
return true;
} }
/* remove item with its id */ /* remove item with its id */
...@@ -732,7 +752,7 @@ void PLModel::rebuild( playlist_item_t *p_root ) ...@@ -732,7 +752,7 @@ void PLModel::rebuild( playlist_item_t *p_root )
/* Invalidate cache */ /* Invalidate cache */
i_cached_id = i_cached_input_id = -1; i_cached_id = i_cached_input_id = -1;
if( rootItem ) RemoveChildren( rootItem ); if( rootItem ) rootItem->removeChildren();
PL_LOCK; PL_LOCK;
if( p_root ) if( p_root )
...@@ -756,27 +776,43 @@ void PLModel::rebuild( playlist_item_t *p_root ) ...@@ -756,27 +776,43 @@ void PLModel::rebuild( playlist_item_t *p_root )
addCallbacks(); addCallbacks();
} }
void PLModel::TakeItem( PLItem *item )
{
assert( item );
PLItem *parent = item->parentItem;
assert( parent );
int i_index = parent->children.indexOf( item );
beginRemoveRows( index( parent, 0 ), i_index, i_index );
parent->takeChildAt( i_index );
endRemoveRows();
}
void PLModel::InsertChildren( PLItem *node, QList<PLItem*>& items, int i_pos )
{
assert( node );
int count = items.size();
if( !count ) return;
beginInsertRows( index( node, 0 ), i_pos, i_pos + count - 1 );
for( int i = 0; i < count; i++ )
{
node->children.insert( i_pos + i, items[i] );
items[i]->parentItem = node;
}
endInsertRows();
}
void PLModel::RemoveItem( PLItem *item ) void PLModel::RemoveItem( PLItem *item )
{ {
if( !item ) return; if( !item ) return;
if( currentItem && currentItem->p_input == item->p_input ) if( currentItem == item )
{ {
currentItem = NULL; currentItem = NULL;
emit currentChanged( QModelIndex() ); emit currentChanged( QModelIndex() );
} }
PLItem *parent = item->parentItem; PLItem *parent = item->parentItem;
assert( parent ); assert( parent );
int i_index = parent->children.indexOf( item ); parent->removeChild( item );
parent->children.removeAt( i_index );
delete item;
}
void PLModel::RemoveChildren( PLItem *root )
{
if( root->children.size() )
{
qDeleteAll( root->children );
root->children.clear();
}
} }
/* This function must be entered WITH the playlist lock */ /* This function must be entered WITH the playlist lock */
...@@ -789,11 +825,17 @@ void PLModel::UpdateChildren( PLItem *root ) ...@@ -789,11 +825,17 @@ void PLModel::UpdateChildren( PLItem *root )
/* This function must be entered WITH the playlist lock */ /* This function must be entered WITH the playlist lock */
void PLModel::UpdateChildren( playlist_item_t *p_node, PLItem *root ) void PLModel::UpdateChildren( playlist_item_t *p_node, PLItem *root )
{ {
playlist_item_t *p_item = playlist_CurrentPlayingItem(p_playlist);
for( int i = 0; i < p_node->i_children ; i++ ) for( int i = 0; i < p_node->i_children ; i++ )
{ {
if( p_node->pp_children[i]->i_flags & PLAYLIST_DBL_FLAG ) continue; if( p_node->pp_children[i]->i_flags & PLAYLIST_DBL_FLAG ) continue;
PLItem *newItem = new PLItem( p_node->pp_children[i], root ); PLItem *newItem = new PLItem( p_node->pp_children[i], root );
root->appendChild( newItem ); root->appendChild( newItem );
if( p_item && newItem->p_input == p_item->p_input )
{
currentItem = newItem;
emit currentChanged( index( currentItem, 0 ) );
}
if( i_depth == DEPTH_PL && p_node->pp_children[i]->i_children != -1 ) if( i_depth == DEPTH_PL && p_node->pp_children[i]->i_children != -1 )
UpdateChildren( p_node->pp_children[i], newItem ); UpdateChildren( p_node->pp_children[i], newItem );
} }
...@@ -901,7 +943,7 @@ void PLModel::sort( int i_root_id, int column, Qt::SortOrder order ) ...@@ -901,7 +943,7 @@ void PLModel::sort( int i_root_id, int column, Qt::SortOrder order )
if( count ) if( count )
{ {
beginRemoveRows( qIndex, 0, count - 1 ); beginRemoveRows( qIndex, 0, count - 1 );
RemoveChildren( item ); item->removeChildren();
endRemoveRows( ); endRemoveRows( );
} }
......
...@@ -151,9 +151,12 @@ private: ...@@ -151,9 +151,12 @@ private:
void recurseDelete( QList<PLItem*> children, QModelIndexList *fullList ); void recurseDelete( QList<PLItem*> children, QModelIndexList *fullList );
void doDeleteItem( PLItem *item, QModelIndexList *fullList ); void doDeleteItem( PLItem *item, QModelIndexList *fullList );
void UpdateTreeItem( PLItem *, bool, bool force = false ); void UpdateTreeItem( PLItem *, bool, bool force = false );
void dropAppendCopy( QByteArray& data, PLItem *target );
void dropMove( QByteArray& data, PLItem *target, int new_pos );
void TakeItem( PLItem * );
void InsertChildren( PLItem *node, QList<PLItem*>& items, int i_pos );
/* The following actions will not signal the view! */ /* The following actions will not signal the view! */
void RemoveItem ( PLItem * ); void RemoveItem ( PLItem * );
void RemoveChildren( PLItem * );
void UpdateChildren( PLItem * ); void UpdateChildren( PLItem * );
void UpdateChildren( playlist_item_t *, PLItem * ); void UpdateChildren( playlist_item_t *, PLItem * );
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment