Commit c54fe5a7 authored by Jakob Leben's avatar Jakob Leben

[PATCH] playlist, Qt4: new playlist_TreeMoveMany()

Add new function which simplifies moving more then one item at a time and
reduces complexity and increases performance of such action.
Also refactor a bit old playlist_TreeMove.
Use new function in Qt4 playlist model.
parent b608f770
...@@ -300,6 +300,7 @@ VLC_EXPORT( int, playlist_AskForArtEnqueue, (playlist_t *, input_item_t *, bool ...@@ -300,6 +300,7 @@ VLC_EXPORT( int, playlist_AskForArtEnqueue, (playlist_t *, input_item_t *, bool
/* Playlist sorting */ /* Playlist sorting */
VLC_EXPORT( int, playlist_TreeMove, ( playlist_t *, playlist_item_t *, playlist_item_t *, int ) ); VLC_EXPORT( int, playlist_TreeMove, ( playlist_t *, playlist_item_t *, playlist_item_t *, int ) );
VLC_EXPORT( int, playlist_TreeMoveMany, ( playlist_t *, int, playlist_item_t **, playlist_item_t *, int ) );
VLC_EXPORT( int, playlist_RecursiveNodeSort, ( playlist_t *, playlist_item_t *,int, int ) ); VLC_EXPORT( int, playlist_RecursiveNodeSort, ( playlist_t *, playlist_item_t *,int, int ) );
VLC_EXPORT( playlist_item_t *, playlist_CurrentPlayingItem, ( playlist_t * ) ); VLC_EXPORT( playlist_item_t *, playlist_CurrentPlayingItem, ( playlist_t * ) );
......
...@@ -217,22 +217,16 @@ bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action, ...@@ -217,22 +217,16 @@ bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action,
if( !parent.isValid()) if( !parent.isValid())
{ {
if( row > -1) if( row > -1)
{
// dropped into top node
p_parent = playlist_ItemGetById( p_playlist, rootItem->i_id ); p_parent = playlist_ItemGetById( p_playlist, rootItem->i_id );
}
else else
{ {
// dropped outside any item
PL_UNLOCK; PL_UNLOCK;
return true; return true;
} }
} }
else else
{
// dropped into/onto an item (depends on (row = -1) or (row > -1))
p_parent = playlist_ItemGetById( p_playlist, itemId ( parent ) ); p_parent = playlist_ItemGetById( p_playlist, itemId ( parent ) );
}
if( !p_parent || p_parent->i_children == -1 ) if( !p_parent || p_parent->i_children == -1 )
{ {
PL_UNLOCK; PL_UNLOCK;
...@@ -248,45 +242,52 @@ bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action, ...@@ -248,45 +242,52 @@ bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action,
QByteArray encodedData = data->data( "vlc/playlist-item-id" ); QByteArray encodedData = data->data( "vlc/playlist-item-id" );
QDataStream stream( &encodedData, QIODevice::ReadOnly ); QDataStream stream( &encodedData, QIODevice::ReadOnly );
/* easiest way to never miss the right index to move to is to if( copy )
track the previously moved item */
playlist_item_t *p_target = NULL;
while( !stream.atEnd() )
{ {
int src_id; while( !stream.atEnd() )
stream >> src_id;
playlist_item_t *p_src = playlist_ItemGetById( p_playlist, src_id );
if( !p_src )
{
PL_UNLOCK;
return false;
}
if( copy )
{ {
input_item_t *input = p_src->p_input; 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, playlist_AddExt ( p_playlist,
p_src->p_input->psz_uri, p_src->p_input->psz_name, p_input->psz_uri, p_input->psz_name,
PLAYLIST_APPEND | PLAYLIST_SPREPARSE, PLAYLIST_END, PLAYLIST_APPEND | PLAYLIST_SPREPARSE, PLAYLIST_END,
input->i_duration, p_input->i_duration,
input->i_options, input->ppsz_options, input->optflagc, p_input->i_options, p_input->ppsz_options, p_input->optflagc,
p_parent == p_playlist->p_local_category, true ); p_parent == p_playlist->p_local_category, true );
continue;
} }
if( !p_target ) }
else
{
QList<int> ids;
while( !stream.atEnd() )
{ {
if ( row == -1 ) row = p_parent->i_children; int id;
playlist_TreeMove( p_playlist, p_src, p_parent, row ); stream >> id;
ids.append(id);
} }
else int count = ids.size();
playlist_item_t *items[count];
for( int i = 0; i < count; i++ )
{ {
for( row = 0 ; row < p_target->p_parent->i_children ; row++ ) playlist_item_t *item = playlist_ItemGetById( p_playlist, ids[i] );
if( p_target->p_parent->pp_children[row] == p_target ) break; if( !item )
playlist_TreeMove( p_playlist, p_src, p_parent, row + 1 ); {
PL_UNLOCK;
return false;
}
items[i] = item;
} }
p_target = p_src; playlist_TreeMoveMany( p_playlist, count, items, p_parent,
(row == -1 ? p_parent->i_children : row) );
} }
PL_UNLOCK; PL_UNLOCK;
/*TODO: That's not a good idea to rebuild the playlist */ /*TODO: That's not a good idea to rebuild the playlist */
rebuild(); rebuild();
......
...@@ -334,6 +334,7 @@ playlist_ServicesDiscoveryAdd ...@@ -334,6 +334,7 @@ playlist_ServicesDiscoveryAdd
playlist_ServicesDiscoveryRemove playlist_ServicesDiscoveryRemove
playlist_Status playlist_Status
playlist_TreeMove playlist_TreeMove
playlist_TreeMoveMany
playlist_Unlock playlist_Unlock
__pl_Hold __pl_Hold
__pl_Release __pl_Release
......
...@@ -672,57 +672,86 @@ playlist_item_t *playlist_ItemFindFromInputAndRoot( playlist_t *p_playlist, ...@@ -672,57 +672,86 @@ playlist_item_t *playlist_ItemFindFromInputAndRoot( playlist_t *p_playlist,
} }
static int TreeMove( playlist_t *p_playlist, playlist_item_t *p_item, static int ItemIndex ( playlist_item_t *p_item )
playlist_item_t *p_node, int i_newpos )
{ {
int j; for( int i = 0; i < p_item->p_parent->i_children; i++ )
playlist_item_t *p_detach = p_item->p_parent; if( p_item->p_parent->pp_children[i] == p_item ) return i;
(void)p_playlist; return -1;
}
/**
* Moves an item
*
* This function must be entered with the playlist lock
*
* \param p_playlist the playlist
* \param p_item the item to move
* \param p_node the new parent of the item
* \param i_newpos the new position under this new parent
* \return VLC_SUCCESS or an error
*/
int playlist_TreeMove( playlist_t * p_playlist, playlist_item_t *p_item,
playlist_item_t *p_node, int i_newpos )
{
PL_ASSERT_LOCKED;
if( p_node->i_children == -1 ) return VLC_EGENERIC; if( p_node->i_children == -1 ) return VLC_EGENERIC;
for( j = 0; j < p_detach->i_children; j++ ) playlist_item_t *p_detach = p_item->p_parent;
{ int i_index = ItemIndex( p_item );
if( p_detach->pp_children[j] == p_item ) break;
}
REMOVE_ELEM( p_detach->pp_children, p_detach->i_children, j );
/* If j < i_newpos, we are moving the element from the top to the REMOVE_ELEM( p_detach->pp_children, p_detach->i_children, i_index );
* down of the playlist. So when removing the element we have
* to change the position as we loose one element if( p_detach == p_node && i_index < i_newpos )
*/
if( p_detach == p_node && j < i_newpos )
i_newpos--; i_newpos--;
/* Attach to new parent */
INSERT_ELEM( p_node->pp_children, p_node->i_children, i_newpos, p_item ); INSERT_ELEM( p_node->pp_children, p_node->i_children, i_newpos, p_item );
p_item->p_parent = p_node; p_item->p_parent = p_node;
pl_priv( p_playlist )->b_reset_currently_playing = true;
vlc_cond_signal( &pl_priv( p_playlist )->signal );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/** /**
* Moves an item * Moves an array of items
* *
* This function must be entered with the playlist lock * This function must be entered with the playlist lock
* *
* \param p_playlist the playlist * \param p_playlist the playlist
* \param p_item the item to move * \param i_items the number of indexes to move
* \param p_node the new parent of the item * \param pp_items the array of indexes to move
* \param i_newpos the new position under this new parent * \param p_node the target node
* \param i_newpos the target position under this node
* \return VLC_SUCCESS or an error * \return VLC_SUCCESS or an error
*/ */
int playlist_TreeMove( playlist_t * p_playlist, playlist_item_t *p_item, int playlist_TreeMoveMany( playlist_t *p_playlist,
playlist_item_t *p_node, int i_newpos ) int i_items, playlist_item_t **pp_items,
playlist_item_t *p_node, int i_newpos )
{ {
int i_ret;
PL_ASSERT_LOCKED; PL_ASSERT_LOCKED;
if( p_node != p_item->p_parent ) return VLC_SUCCESS; if ( p_node->i_children == -1 ) return VLC_EGENERIC;
i_ret = TreeMove( p_playlist, p_item, p_node, i_newpos );
pl_priv(p_playlist)->b_reset_currently_playing = true; int i;
vlc_cond_signal( &pl_priv(p_playlist)->signal ); for( i = 0; i < i_items; i++ )
return i_ret; {
playlist_item_t *p_item = pp_items[i];
int i_index = ItemIndex( p_item );
playlist_item_t *p_parent = p_item->p_parent;
REMOVE_ELEM( p_parent->pp_children, p_parent->i_children, i_index );
if ( p_parent == p_node && i_index < i_newpos ) i_newpos--;
}
for( i = i_items - 1; i >= 0; i-- )
{
playlist_item_t *p_item = pp_items[i];
INSERT_ELEM( p_node->pp_children, p_node->i_children, i_newpos, p_item );
p_item->p_parent = p_node;
}
pl_priv( p_playlist )->b_reset_currently_playing = true;
vlc_cond_signal( &pl_priv( p_playlist )->signal );
return VLC_SUCCESS;
} }
/** /**
......
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