Commit 0f968b65 authored by Clément Stenac's avatar Clément Stenac

Playtree: handle delete nicely

parent ed9e26d2
......@@ -71,6 +71,13 @@ void CmdPlaytreeAppend::execute()
rVar.onAppend( m_pAdd );
}
void CmdPlaytreeDelete::execute()
{
// Notify the playtree variable
Playtree &rVar = VlcProc::instance( getIntf() )->getPlaytreeVar();
rVar.onDelete( m_id );
}
void CmdSetText::execute()
{
// Change the text variable
......
......@@ -77,6 +77,26 @@ class CmdPlaytreeAppend: public CmdGeneric
playlist_add_t * m_pAdd;
};
/// Command to notify the playtree of an item deletion
class CmdPlaytreeDelete: public CmdGeneric
{
public:
CmdPlaytreeDelete( intf_thread_t *pIntf, int i_id ) :
CmdGeneric( pIntf ), m_id( i_id ) {}
virtual ~CmdPlaytreeDelete() {}
/// This method does the real job of the command
virtual void execute();
/// Return the type of the command
virtual string getType() const { return "playtree append"; }
private:
int m_id;
};
/// Command to set a text variable
class CmdSetText: public CmdGeneric
......
......@@ -150,7 +150,22 @@ void CtrlTree::onUpdate( Subject<VarTree, tree_update*> &rTree,
}
else if ( arg->i_type == 2 ) // Item-append
{
/// \todo Check if the item is really visible in the view (we only check if it in the document)
/// \todo Check if the item is really visible in the view
// (we only check if it in the document)
if( arg->b_visible == true )
{
makeImage();
}
}
else if( arg->i_type == 3 ) // item-del
{
/* Make sure firstPos and lastSelected are still valid */
while( m_firstPos->m_deleted && m_firstPos != m_rTree.root()->begin() )
{
m_firstPos = m_rTree.getPrevVisibleItem( m_firstPos );
}
if( m_firstPos->m_deleted ) m_firstPos = m_rTree.root()->begin();
if( arg->b_visible == true )
{
makeImage();
......@@ -453,27 +468,30 @@ void CtrlTree::handleEvent( EvtGeneric &rEvent )
string::npos )
{
it = findItemAtPos(yPos);
if( it->size() && xPos > (it->depth() - 1) * itemImageWidth()
&& xPos < it->depth() * itemImageWidth() )
{
// Fold/unfold the item
it->m_expanded = !it->m_expanded;
bChangedPosition = true;
}
else
if( it != m_rTree.end() )
{
// Unselect any previously selected item
VarTree::Iterator it2;
for( it2 = m_rTree.begin(); it2 != m_rTree.end();
it2 = m_rTree.getNextVisibleItem( it2 ) )
if( it->size() && xPos > (it->depth() - 1) * itemImageWidth()
&& xPos < it->depth() * itemImageWidth() )
{
it2->m_selected = false;
// Fold/unfold the item
it->m_expanded = !it->m_expanded;
bChangedPosition = true;
}
// Select the new item
if( it != m_rTree.end() )
else
{
it->m_selected = true;
m_pLastSelected = &*it;
// Unselect any previously selected item
VarTree::Iterator it2;
for( it2 = m_rTree.begin(); it2 != m_rTree.end();
it2 = m_rTree.getNextVisibleItem( it2 ) )
{
it2->m_selected = false;
}
// Select the new item
if( it != m_rTree.end() )
{
it->m_selected = true;
m_pLastSelected = &*it;
}
}
}
}
......@@ -666,7 +684,10 @@ void CtrlTree::makeImage()
m_pImage->fillRect( 0, yPos, width, rectHeight,
m_selColor );
}
it = m_rTree.getNextVisibleItem( it );
do
{
it = m_rTree.getNextVisibleItem( it );
} while( it->m_deleted );
}
}
}
......@@ -683,7 +704,10 @@ void CtrlTree::makeImage()
{
uint32_t color = ( it->m_selected ? m_selColor : bgColor );
m_pImage->fillRect( 0, yPos, width, rectHeight, color );
it = m_rTree.getNextVisibleItem( it );
do
{
it = m_rTree.getNextVisibleItem( it );
} while( it->m_deleted );
}
else
{
......@@ -746,7 +770,9 @@ void CtrlTree::makeImage()
yPos += (pText->getHeight() - ySrc );
delete pText;
}
do {
it = m_rTree.getNextVisibleItem( it );
} while( it->m_deleted );
}
}
......
......@@ -128,7 +128,7 @@ VlcProc::VlcProc( intf_thread_t *pIntf ): SkinObject( pIntf ),
// Called when a playlist item is deleted
// TODO: properly handle item-deleted
var_AddCallback( pIntf->p_sys->p_playlist, "item-deleted",
onIntfChange, this );
onItemDelete, this );
// Called when the "interface shower" wants us to show the skin
var_AddCallback( pIntf->p_sys->p_playlist, "intf-show",
onIntfShow, this );
......@@ -174,7 +174,7 @@ VlcProc::~VlcProc()
var_DelCallback( getIntf()->p_sys->p_playlist, "item-append",
onItemAppend, this );
var_DelCallback( getIntf()->p_sys->p_playlist, "item-deleted",
onIntfChange, this );
onItemDelete, this );
var_DelCallback( getIntf()->p_sys->p_playlist, "intf-show",
onIntfShow, this );
var_DelCallback( getIntf()->p_sys->p_playlist, "playlist-current",
......@@ -443,6 +443,31 @@ int VlcProc::onItemAppend( vlc_object_t *pObj, const char *pVariable,
return VLC_SUCCESS;
}
int VlcProc::onItemDelete( vlc_object_t *pObj, const char *pVariable,
vlc_value_t oldVal, vlc_value_t newVal,
void *pParam )
{
VlcProc *pThis = (VlcProc*)pParam;
int i_id = newVal.i_int;
CmdGenericPtr ptrTree;
CmdPlaytreeDelete *pCmdTree = new CmdPlaytreeDelete( pThis->getIntf(),
i_id);
ptrTree = CmdGenericPtr( pCmdTree );
// Create a playlist notify command (for old style playlist)
CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
// Push the command in the asynchronous command queue
AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
pQueue->push( CmdGenericPtr( pCmd ) );
pQueue->push( ptrTree , false );
return VLC_SUCCESS;
}
int VlcProc::onPlaylistChange( vlc_object_t *pObj, const char *pVariable,
......
......@@ -173,6 +173,12 @@ class VlcProc: public SkinObject
vlc_value_t oldVal, vlc_value_t newVal,
void *pParam );
/// Callback for item-change variable
static int onItemDelete( vlc_object_t *pObj, const char *pVariable,
vlc_value_t oldVal, vlc_value_t newVal,
void *pParam );
/// Callback for playlist-current variable
static int onPlaylistChange( vlc_object_t *pObj, const char *pVariable,
vlc_value_t oldVal, vlc_value_t newVal,
......
......@@ -28,7 +28,8 @@ const string VarTree::m_type = "tree";
VarTree::VarTree( intf_thread_t *pIntf )
: Variable( pIntf ), m_id( 0 ), m_selected( false ), m_playing( false ),
m_expanded( false ), m_pData( NULL ), m_pParent( NULL )
m_expanded( false ), m_deleted( false ), m_readonly( false),
m_pData( NULL ), m_pParent( NULL )
{
// Create the position variable
m_cPosition = VariablePtr( new VarPercent( pIntf ) );
......@@ -37,11 +38,14 @@ VarTree::VarTree( intf_thread_t *pIntf )
VarTree::VarTree( intf_thread_t *pIntf, VarTree *pParent, int id,
const UStringPtr &rcString, bool selected, bool playing,
bool expanded, void *pData )
bool expanded, bool readonly,
void *pData )
: Variable( pIntf ), m_id( id ), m_cString( rcString ),
m_selected( selected ), m_playing( playing ), m_expanded( expanded ),
m_deleted( false ), m_readonly( readonly ),
m_pData( pData ), m_pParent( pParent )
{
fprintf( stderr, "Expanded is %i - RO %i\n", m_expanded, m_readonly );
// Create the position variable
m_cPosition = VariablePtr( new VarPercent( pIntf ) );
getPositionVar().set( 1.0 );
......@@ -53,10 +57,12 @@ VarTree::~VarTree()
}
void VarTree::add( int id, const UStringPtr &rcString, bool selected,
bool playing, bool expanded, void *pData )
bool playing, bool expanded, bool readonly,
void *pData )
{
m_children.push_back( VarTree( getIntf(), this, id, rcString, selected,
playing, expanded, pData ) );
playing, expanded, readonly,
pData ) );
}
void VarTree::delSelected()
......@@ -105,6 +111,22 @@ VarTree::ConstIterator VarTree::operator[]( int n ) const
return it;
}
VarTree::Iterator VarTree::getNextSibling( VarTree::Iterator current )
{
VarTree *p_parent = current->parent();
if( p_parent && current != p_parent->end() )
{
Iterator it = current->parent()->begin();
while( it != p_parent->end() && it != current ) it++;
if( it != p_parent->end() )
{
it++;
}
return root()->end();
}
return root()->end();
}
/* find iterator to next ancestor
* ... which means parent++ or grandparent++ or grandgrandparent++ ... */
VarTree::Iterator VarTree::next_uncle()
......
......@@ -49,7 +49,7 @@ class VarTree: public Variable, public Subject<VarTree, tree_update*>
VarTree( intf_thread_t *pIntf, VarTree *pParent, int id,
const UStringPtr &rcString, bool selected, bool playing,
bool expanded, void *pData );
bool expanded,bool readonly, void *pData );
virtual ~VarTree();
......@@ -58,7 +58,8 @@ class VarTree: public Variable, public Subject<VarTree, tree_update*>
/// Add a pointer on string in the children's list
virtual void add( int id, const UStringPtr &rcString, bool selected,
bool playing, bool expanded, void *pData );
bool playing, bool expanded, bool readonly,
void *pData );
/// Remove the selected item from the children's list
virtual void delSelected();
......@@ -72,8 +73,11 @@ class VarTree: public Variable, public Subject<VarTree, tree_update*>
bool m_selected;
bool m_playing;
bool m_expanded;
bool m_deleted;
void *m_pData;
inline bool isReadonly() { return m_readonly; };
/// Get the number of children
int size() const { return m_children.size(); }
......@@ -100,6 +104,9 @@ class VarTree: public Variable, public Subject<VarTree, tree_update*>
VarTree *parent() { return m_pParent; }
void checkParents( VarTree *pParent );
/// Get next sibling
Iterator getNextSibling( Iterator );
Iterator next_uncle();
Iterator prev_uncle();
......@@ -122,6 +129,11 @@ class VarTree: public Variable, public Subject<VarTree, tree_update*>
return depth;
}
void removeChild( VarTree::Iterator item )
{
m_children.erase( item );
}
/// Execute the action associated to this item
virtual void action( VarTree *pItem ) {}
......@@ -160,6 +172,8 @@ class VarTree: public Variable, public Subject<VarTree, tree_update*>
/// Pointer to parent node
VarTree *m_pParent;
bool m_readonly;
/// Variable type
static const string m_type;
......
......@@ -58,31 +58,49 @@ Playtree::~Playtree()
void Playtree::delSelected()
{
Iterator it;
for (it = begin(); it != end() ; it = getNextVisibleItem( it ) )
Iterator it = begin();
vlc_mutex_lock( &getIntf()->p_sys->p_playlist->object_lock );
for( it = begin(); it != end(); it = getNextVisibleItem( it ) )
{
if( (*it).m_selected )
if( (*it).m_selected && !(*it).isReadonly() )
{
(*it).m_deleted = true;
}
}
/// \todo Do this better (handle item-deleted)
tree_update descr;
descr.i_type = 3;
notify( &descr );
it = begin();
while( it != end() )
{
if( (*it).m_deleted )
{
VarTree::Iterator it2;
playlist_item_t *p_item = (playlist_item_t *)(it->m_pData);
if( p_item->i_children == -1 )
{
playlist_LockDelete( getIntf()->p_sys->p_playlist,
playlist_Delete( getIntf()->p_sys->p_playlist,
p_item->input.i_id );
it2 = getNextVisibleItem( it ) ;
it->parent()->removeChild( it );
it = it2;
}
else
{
vlc_mutex_lock( &getIntf()->p_sys->p_playlist->object_lock );
playlist_NodeDelete( getIntf()->p_sys->p_playlist, p_item,
VLC_TRUE, VLC_FALSE );
vlc_mutex_unlock( &getIntf()->p_sys->p_playlist->object_lock );
it2 = getNextSibling( it );
it->parent()->removeChild( it );
it = it2;
}
}
else
{
it = getNextVisibleItem( it );
}
}
/// \todo Do this better (handle item-deleted)
buildTree();
tree_update descr;
descr.i_type = 1;
notify( &descr );
vlc_mutex_unlock( &getIntf()->p_sys->p_playlist->object_lock );
}
void Playtree::action( VarTree *pItem )
......@@ -137,6 +155,23 @@ void Playtree::onUpdateItem( int id )
notify( &descr );
}
/// \todo keep a list of "recently removed" to avoid looking up if we
// already removed it
void Playtree::onDelete( int i_id )
{
tree_update descr;
descr.i_id = i_id;
descr.i_type = 3;
Iterator item = findById( i_id ) ;
if( item != end() )
{
if( item->parent() )
item->parent()->removeChild( item );
descr.b_visible = item->parent() ? true : item->parent()->m_expanded;
notify( &descr );
}
}
void Playtree::onAppend( playlist_add_t *p_add )
{
i_items_to_append --;
......@@ -152,7 +187,8 @@ void Playtree::onAppend( playlist_add_t *p_add )
if( !p_item ) return;
UString *pName = new UString( getIntf(), p_item->input.psz_name );
node->add( p_add->i_item, UStringPtr( pName ),
false,false, false, p_item );
false,false, false, p_item->i_flags & PLAYLIST_RO_FLAG,
p_item );
}
}
tree_update descr;
......@@ -172,7 +208,8 @@ void Playtree::buildNode( playlist_item_t *pNode, VarTree &rTree )
rTree.add( pNode->pp_children[i]->input.i_id, UStringPtr( pName ),
false,
m_pPlaylist->status.p_item == pNode->pp_children[i],
false, pNode->pp_children[i] );
false, pNode->pp_children[i]->i_flags & PLAYLIST_RO_FLAG,
pNode->pp_children[i] );
if( pNode->pp_children[i]->i_children )
{
buildNode( pNode->pp_children[i], rTree.back() );
......
......@@ -48,6 +48,9 @@ class Playtree: public VarTree
/// Function called to notify playlist item append
void onAppend( playlist_add_t * );
/// Function called to notify playlist item delete
void onDelete( int );
/// Items waiting to be appended
int i_items_to_append;
......
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