Some more Qt playlist code
[vlc.git] / modules / gui / qt4 / playlist_model.cpp
index f6f8f57..f5810dd 100644 (file)
@@ -42,19 +42,31 @@ static int ItemDeleted( vlc_object_t *p_this, const char *psz_variable,
  * Playlist item implementation
  *************************************************************************/
 
-PLItem::PLItem( int _i_id, int _i_input_id, PLItem *parent, PLModel *m)
+/**
+ * Column strings
+ *      Title
+ *      Artist
+ *      Duration
+ */
+
+void PLItem::init( int _i_id, int _i_input_id, PLItem *parent, PLModel *m)
 {
     parentItem = parent;
     i_id = _i_id; i_input_id = _i_input_id;
     model = m;
+    strings.append( "" );    
+    strings.append( "" );    
+    strings.append( "" );    
+}
+
+PLItem::PLItem( int _i_id, int _i_input_id, PLItem *parent, PLModel *m)
+{
+    init( _i_id, _i_input_id, parent, m );
 }
 
 PLItem::PLItem( playlist_item_t * p_item, PLItem *parent, PLModel *m )
 {
-    i_id = p_item->i_id;
-    i_input_id = p_item->p_input->i_id;
-    parentItem = parent;
-    model = m;
+    init( p_item->i_id, p_item->p_input->i_id, parent, m );
 }
 
 PLItem::~PLItem()
@@ -62,12 +74,15 @@ PLItem::~PLItem()
     qDeleteAll(children);
 }
 
-void PLItem::insertChild( PLItem *item, int i_pos )
+void PLItem::insertChild( PLItem *item, int i_pos, bool signal )
 {
     assert( model );
-    model->beginInsertRows( model->index( this , 0 ), i_pos, i_pos );
+    fprintf( stderr, "Inserting child \n" );
+    if( signal )
+        model->beginInsertRows( model->index( this , 0 ), i_pos, i_pos );
     children.append( item );
-    model->endInsertRows();
+    if( signal )
+        model->endInsertRows();
 }
 
 int PLItem::row() const
@@ -77,21 +92,40 @@ int PLItem::row() const
     return 0;
 }
 
+void PLItem::update( playlist_item_t *p_item )
+{
+    assert( p_item->p_input->i_id == i_input_id );
+    strings[0] = QString::fromUtf8( p_item->p_input->psz_name );
+}
 
 /*************************************************************************
  * Playlist model implementation
  *************************************************************************/
 
-PLModel::PLModel( playlist_item_t * p_root, int i_depth, QObject *parent)
+PLModel::PLModel( playlist_t *_p_playlist,
+                  playlist_item_t * p_root, int i_depth, QObject *parent)
                                     : QAbstractItemModel(parent)
 {
-    rootItem = new PLItem( p_root, NULL, this );
-
+     rootItem = NULL;
+        rootItem = new PLItem( p_root, NULL, this );
+    fprintf( stderr, "%i -> %i, %i -> %i", p_root->i_id, rootItem->i_id, p_root->p_input->i_id, rootItem->i_input_id );
+    p_playlist= _p_playlist;
     i_items_to_append = 0;
     b_need_update     = false;
     i_cached_id       = -1;
     i_cached_input_id = -1;
 
+    addCallbacks();
+}
+
+PLModel::~PLModel()
+{
+    delCallbacks();
+    delete rootItem;
+}
+
+void PLModel::addCallbacks()
+{
     /* Some global changes happened -> Rebuild all */
     var_AddCallback( p_playlist, "intf-change", PlaylistChanged, this );
     /* We went to the next item */
@@ -102,17 +136,17 @@ PLModel::PLModel( playlist_item_t * p_root, int i_depth, QObject *parent)
     var_AddCallback( p_playlist, "item-deleted", ItemDeleted, this );
 }
 
-PLModel::~PLModel()
+void PLModel::delCallbacks()
 {
     var_DelCallback( p_playlist, "item-change", ItemChanged, this );
     var_DelCallback( p_playlist, "playlist-current", PlaylistNext, this );
     var_DelCallback( p_playlist, "intf-change", PlaylistChanged, this );
     var_DelCallback( p_playlist, "item-append", ItemAppended, this );
     var_DelCallback( p_playlist, "item-deleted", ItemDeleted, this );
-    delete rootItem;
 }
 
 /****************** Base model mandatory implementations *****************/
+
 QVariant PLModel::data(const QModelIndex &index, int role) const
 {
     if (!index.isValid())
@@ -180,7 +214,17 @@ QModelIndex PLModel::parent(const QModelIndex &index) const
     return createIndex(parentItem->row(), 0, parentItem);
 }
 
+int PLModel::columnCount( const QModelIndex &i) const 
+{
+    return 1;
+}
+
 int PLModel::childrenCount(const QModelIndex &parent) const
+{
+    return rowCount( parent );
+}
+
+int PLModel::rowCount(const QModelIndex &parent) const
 {
     PLItem *parentItem;
 
@@ -252,6 +296,7 @@ PLItem * PLModel::FindInner( PLItem *root, int i_id, bool b_input )
                 return childFound;
             } 
         }
+        it++;
     }
     return NULL;
 }
@@ -272,15 +317,18 @@ void PLModel::customEvent( QEvent *event )
         ProcessItemRemoval( ple->i_id );
 }
 
+/**** Events processing ****/
 void PLModel::ProcessInputItemUpdate( int i_input_id )
 {
-    assert( i_input_id >= 0 );
-    /// \todo
+    if( i_input_id <= 0 ) return;
+    PLItem *item = FindByInput( rootItem, i_input_id );
+    fprintf( stderr, "Updating %i -> %p \n", i_input_id, item );
+    UpdateTreeItem( item, true );
 }
 
 void PLModel::ProcessItemRemoval( int i_id )
 {
-    assert( i_id >= 0 );
+    if( i_id <= 0 ) return;
     if( i_id == i_cached_id ) i_cached_id = -1;
     i_cached_input_id = -1;
 
@@ -290,6 +338,7 @@ void PLModel::ProcessItemRemoval( int i_id )
 void PLModel::ProcessItemAppend( playlist_add_t *p_add )
 {
     playlist_item_t *p_item = NULL;
+    PLItem *newItem = NULL;
     i_items_to_append--;
     if( b_need_update ) return;
 
@@ -299,12 +348,70 @@ void PLModel::ProcessItemAppend( playlist_add_t *p_add )
     p_item = playlist_ItemGetById( p_playlist, p_add->i_item );
     if( !p_item || p_item->i_flags & PLAYLIST_DBL_FLAG ) goto end;
 
-    nodeItem->appendChild( new PLItem( p_item, nodeItem, this ) );
-
+    newItem = new PLItem( p_item, nodeItem, this );
+    nodeItem->appendChild( newItem );
+    UpdateTreeItem( p_item, newItem, true );
 
 end:
     return;
 }
+
+void PLModel::Rebuild()
+{
+    /* Remove callbacks before locking to avoid deadlocks */
+    delCallbacks();
+    PL_LOCK;
+
+    /* Invalidate cache */
+    i_cached_id = i_cached_input_id = -1;
+
+    /* Clear the tree */
+    qDeleteAll( rootItem->children );
+
+    /* Recreate from root */
+    UpdateNodeChildren( rootItem );
+
+    /* And signal the view */
+    emit layoutChanged();
+
+    addCallbacks();
+    PL_UNLOCK;
+}
+
+void PLModel::UpdateNodeChildren( PLItem *root )
+{
+    playlist_item_t *p_node = playlist_ItemGetById( p_playlist, root->i_id );
+    UpdateNodeChildren( p_node, root );
+}
+
+void PLModel::UpdateNodeChildren( playlist_item_t *p_node, PLItem *root )
+{
+    for( int i = 0; i < p_node->i_children ; i++ )
+    {
+        PLItem *newItem =  new PLItem( p_node->pp_children[i], root, this );
+        fprintf( stderr, "New %p\n", newItem );
+        root->appendChild( newItem, false );
+        UpdateTreeItem( newItem, false );
+        if( p_node->pp_children[i]->i_children != -1 )
+            UpdateNodeChildren( p_node->pp_children[i], newItem );
+    }
+}
+
+void PLModel::UpdateTreeItem( PLItem *item, bool signal )
+{
+    playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id );
+    UpdateTreeItem( p_item, item, signal );
+}
+
+void PLModel::UpdateTreeItem( playlist_item_t *p_item, PLItem *item, bool signal ) 
+{
+    /// \todo
+    fprintf( stderr, "Updating item %s\n", p_item->p_input->psz_name );
+    item->update( p_item );
+    if( signal )
+    {    // emit 
+    }
+}
         
 /**********************************************************************
  * Playlist callbacks