]> git.sesse.net Git - vlc/blobdiff - modules/gui/qt4/components/playlist/playlist_model.cpp
qt4: move item removal from PLItem to PLModel...
[vlc] / modules / gui / qt4 / components / playlist / playlist_model.cpp
index 7fc6fe8f1ba22a2955b9ec445f788939dd2bc0e7..30f4c6023ed27475a488d983e9189784461d4105 100644 (file)
@@ -111,18 +111,6 @@ PLModel::PLModel( playlist_t *_p_playlist,  /* THEPL */
             this, ProcessInputItemUpdate( input_item_t *) );
     CONNECT( THEMIM, inputChanged( input_thread_t * ),
             this, ProcessInputItemUpdate( input_thread_t* ) );
-    PL_LOCK;
-    playlist_item_t *p_item;
-    /* Check if there's allready some item playing when playlist
-     * model is created, if so, tell model that it's currentone
-     */
-    if( (p_item = playlist_CurrentPlayingItem(p_playlist)) )
-    {
-        currentItem = FindByInput( rootItem,
-                                           p_item->p_input->i_id );
-        emit currentChanged( index( currentItem, 0 ) );
-    }
-    PL_UNLOCK;
 }
 
 PLModel::~PLModel()
@@ -301,8 +289,7 @@ bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action,
 void PLModel::removeItem( int i_id )
 {
     PLItem *item = FindById( rootItem, i_id );
-    if( currentItem && item && currentItem->p_input == item->p_input ) currentItem = NULL;
-    if( item ) item->remove( item, i_depth );
+    RemoveItem( item );
 }
 
 /* callbacks and slots */
@@ -361,10 +348,6 @@ QVariant PLModel::data( const QModelIndex &index, int role ) const
     PLItem *item = static_cast<PLItem*>(index.internalPointer());
     if( role == Qt::DisplayRole )
     {
-        int running_index = -1;
-        int columncount = 0;
-        int metadata = 1;
-
         if( i_depth == DEPTH_SEL )
         {
             vlc_mutex_lock( &item->p_input->lock );
@@ -373,16 +356,8 @@ QVariant PLModel::data( const QModelIndex &index, int role ) const
             return QVariant(returninfo);
         }
 
-        while( metadata < COLUMN_END )
-        {
-            if( i_showflags & metadata )
-                running_index++;
-            if( running_index == index.column() )
-                break;
-            metadata <<= 1;
-        }
-
-        if( running_index != index.column() ) return QVariant();
+        int metadata = metaColumn( index.column() );
+        if( metadata == COLUMN_END ) return QVariant();
 
         QString returninfo;
         if( metadata == COLUMN_NUMBER )
@@ -390,7 +365,7 @@ QVariant PLModel::data( const QModelIndex &index, int role ) const
         else
         {
             char *psz = psz_column_meta( item->p_input, metadata );
-            returninfo = QString( qfu( psz ) );
+            returninfo = qfu( psz );
             free( psz );
         }
         return QVariant( returninfo );
@@ -427,25 +402,16 @@ int PLModel::itemId( const QModelIndex &index ) const
 QVariant PLModel::headerData( int section, Qt::Orientation orientation,
                               int role ) const
 {
-    int metadata=1;
-    int running_index=-1;
     if (orientation != Qt::Horizontal || role != Qt::DisplayRole)
         return QVariant();
 
     if( i_depth == DEPTH_SEL ) return QVariant( QString("") );
 
-    while( metadata < COLUMN_END )
-    {
-        if( metadata & i_showflags )
-            running_index++;
-        if( running_index == section )
-            break;
-        metadata <<= 1;
-    }
+    int meta_col = metaColumn( section );
 
-    if( running_index != section ) return QVariant();
+    if( meta_col == COLUMN_END ) return QVariant();
 
-    return QVariant( qfu( psz_column_title( metadata ) ) );
+    return QVariant( qfu( psz_column_title( meta_col ) ) );
 }
 
 QModelIndex PLModel::index( int row, int column, const QModelIndex &parent )
@@ -653,6 +619,24 @@ PLItem * PLModel::FindInner( PLItem *root, int i_id, bool b_input )
 #undef CACHE
 #undef ICACHE
 
+/* computes column id of meta data from visible column index */
+int PLModel::metaColumn( int column ) const
+{
+    int metadata = 1;
+    int running_index = -1;
+
+    while( metadata < COLUMN_END )
+    {
+        if( metadata & i_showflags )
+            running_index++;
+        if( running_index == column )
+            break;
+        metadata <<= 1;
+    }
+
+    if( running_index != column ) return COLUMN_END;
+    return metadata;
+}
 
 /************************* Updates handling *****************************/
 void PLModel::customEvent( QEvent *event )
@@ -723,11 +707,9 @@ void PLModel::ProcessItemAppend( const playlist_add_t *p_add )
     newItem = new PLItem( p_item, nodeItem );
     PL_UNLOCK;
 
-    emit layoutAboutToBeChanged();
-    emit beginInsertRows( index( newItem, 0 ), nodeItem->childCount(), nodeItem->childCount()+1 );
+    beginInsertRows( index( nodeItem, 0 ), nodeItem->childCount(), nodeItem->childCount() );
     nodeItem->appendChild( newItem );
-    emit endInsertRows();
-    emit layoutChanged();
+    endInsertRows();
     UpdateTreeItem( newItem, true );
     return;
 end:
@@ -749,20 +731,8 @@ void PLModel::rebuild( playlist_item_t *p_root )
     /* Invalidate cache */
     i_cached_id = i_cached_input_id = -1;
 
-    emit layoutAboutToBeChanged();
+    if( rootItem ) RemoveChildren( rootItem );
 
-    /* Clear the tree */
-    if( rootItem )
-    {
-        if( rootItem->children.size() )
-        {
-            emit beginRemoveRows( index( rootItem, 0 ), 0,
-                    rootItem->children.size() -1 );
-            qDeleteAll( rootItem->children );
-            rootItem->children.clear();
-            emit endRemoveRows();
-        }
-    }
     PL_LOCK;
     if( p_root )
     {
@@ -771,49 +741,60 @@ void PLModel::rebuild( playlist_item_t *p_root )
     }
     assert( rootItem );
     /* Recreate from root */
-    UpdateNodeChildren( rootItem );
+    UpdateChildren( rootItem );
     if( (p_item = playlist_CurrentPlayingItem(p_playlist)) )
-    {
-        currentItem = FindByInput( rootItem,
-                                           p_item->p_input->i_id );
-        if( currentItem )
-        {
-            UpdateTreeItem( currentItem, true, false );
-        }
-    }
+        currentItem = FindByInput( rootItem, p_item->p_input->i_id );
     else
-    {
         currentItem = NULL;
-    }
     PL_UNLOCK;
 
     /* And signal the view */
-    emit layoutChanged();
+    reset();
+    emit currentChanged( index( currentItem, 0 ) );
+
     addCallbacks();
 }
 
+void PLModel::RemoveItem( PLItem *item )
+{
+    if( !item ) return;
+    if( currentItem && currentItem->p_input == item->p_input )
+    {
+        currentItem = NULL;
+        emit currentChanged( QModelIndex() );
+    }
+    PLItem *parent = item->parentItem;
+    assert( parent );
+    int i_index = parent->children.indexOf( 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 */
-void PLModel::UpdateNodeChildren( PLItem *root )
+void PLModel::UpdateChildren( PLItem *root )
 {
-    emit layoutAboutToBeChanged();
     playlist_item_t *p_node = playlist_ItemGetById( p_playlist, root->i_id );
-    UpdateNodeChildren( p_node, root );
-    emit layoutChanged();
+    UpdateChildren( p_node, root );
 }
 
 /* This function must be entered WITH the playlist lock */
-void PLModel::UpdateNodeChildren( playlist_item_t *p_node, PLItem *root )
+void PLModel::UpdateChildren( playlist_item_t *p_node, PLItem *root )
 {
     for( int i = 0; i < p_node->i_children ; i++ )
     {
         if( p_node->pp_children[i]->i_flags & PLAYLIST_DBL_FLAG ) continue;
         PLItem *newItem =  new PLItem( p_node->pp_children[i], root );
-        emit beginInsertRows( index( newItem, 0 ), root->childCount(), root->childCount()+1 );
         root->appendChild( newItem );
-        emit endInsertRows();
-        UpdateTreeItem( newItem, true, true );
         if( i_depth == DEPTH_PL && p_node->pp_children[i]->i_children != -1 )
-            UpdateNodeChildren( p_node->pp_children[i], newItem );
+            UpdateChildren( p_node->pp_children[i], newItem );
     }
 }
 
@@ -883,14 +864,19 @@ void PLModel::doDeleteItem( PLItem *item, QModelIndexList *fullList )
         playlist_NodeDelete( p_playlist, p_item, true, false );
     PL_UNLOCK;
     /* And finally, remove it from the tree */
-    emit beginRemoveRows( index( item->parentItem, 0), item->parentItem->children.indexOf( item ),
-            item->parentItem->children.indexOf( item )+1 );
-    item->remove( item, i_depth );
-    emit endRemoveRows();
+    int itemIndex = item->parentItem->children.indexOf( item );
+    beginRemoveRows( index( item->parentItem, 0), itemIndex, itemIndex );
+    RemoveItem( item );
+    endRemoveRows();
 }
 
 /******* Volume III: Sorting and searching ********/
 void PLModel::sort( int column, Qt::SortOrder order )
+{
+    sort( rootItem->i_id, column, order );
+}
+
+void PLModel::sort( int i_root_id, int column, Qt::SortOrder order )
 {
     int i_index = -1;
     int i_flag = 0;
@@ -903,16 +889,25 @@ void PLModel::sort( int column, Qt::SortOrder order )
         if( column == i_index )
         {
             i_flag = i_column;
-            goto next;
+            break;
         }
     }
 
+    PLItem *item = FindById( rootItem, i_root_id );
+    if( !item ) return;
+    QModelIndex qIndex = index( item, 0 );
+    int count = item->children.size();
+    if( count )
+    {
+        beginRemoveRows( qIndex, 0, count - 1 );
+        RemoveChildren( item );
+        endRemoveRows( );
+    }
 
-next:
     PL_LOCK;
     {
         playlist_item_t *p_root = playlist_ItemGetById( p_playlist,
-                                                        rootItem->i_id );
+                                                        i_root_id );
         if( p_root && i_flag )
         {
             playlist_RecursiveNodeSort( p_playlist, p_root,
@@ -921,8 +916,13 @@ next:
                                             ORDER_NORMAL : ORDER_REVERSE );
         }
     }
+    if( count )
+    {
+        beginInsertRows( qIndex, 0, count - 1 );
+        UpdateChildren( item );
+        endInsertRows( );
+    }
     PL_UNLOCK;
-    rebuild();
 }
 
 void PLModel::search( const QString& search_text )
@@ -943,57 +943,56 @@ void PLModel::search( const QString& search_text )
 /*********** Popup *********/
 void PLModel::popup( QModelIndex & index, QPoint &point, QModelIndexList list )
 {
-    int i_id;
-    if( index.isValid() ) i_id = itemId( index );
-    else i_id = rootItem->i_id;
+    int i_id = index.isValid() ? itemId( index ) : rootItem->i_id;
+
     PL_LOCK;
     playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id );
-    if( p_item )
+    if( !p_item )
     {
-        i_popup_item = p_item->i_id;
-        i_popup_parent = p_item->p_parent ? p_item->p_parent->i_id : -1;
-        bool node = p_item->i_children > -1;
-        bool tree = false;
-        if( node )
-        {
-            /* check whether we are in tree view */
-            playlist_item_t *p_up = p_item;
-            while( p_up )
-            {
-                if ( p_up == p_playlist->p_root_category ) tree = true;
-                p_up = p_up->p_parent;
-            }
-        }
-        PL_UNLOCK;
+        PL_UNLOCK; return;
+    }
+    i_popup_item = index.isValid() ? p_item->i_id : -1;
+    i_popup_parent = index.isValid() ?
+        ( p_item->p_parent ? p_item->p_parent->i_id : -1 ) :
+        ( p_item->i_id );
+    i_popup_column = index.column();
+    /* check whether we are in tree view */
+    bool tree = false;
+    playlist_item_t *p_up = p_item;
+    while( p_up )
+    {
+        if ( p_up == p_playlist->p_root_category ) tree = true;
+        p_up = p_up->p_parent;
+    }
+    PL_UNLOCK;
 
-        current_selection = list;
-        QMenu *menu = new QMenu;
-        if( index.isValid() )
-        {
-            menu->addAction( qtr(I_POP_PLAY), this, SLOT( popupPlay() ) );
-            menu->addAction( qtr(I_POP_DEL), this, SLOT( popupDel() ) );
-            menu->addSeparator();
-            menu->addAction( qtr(I_POP_STREAM), this, SLOT( popupStream() ) );
-            menu->addAction( qtr(I_POP_SAVE), this, SLOT( popupSave() ) );
-            menu->addSeparator();
-            menu->addAction( qtr(I_POP_INFO), this, SLOT( popupInfo() ) );
-            if( node )
-            {
-                menu->addSeparator();
-                menu->addAction( qtr(I_POP_SORT), this, SLOT( popupSort() ) );
-            }
-        }
-        if( node && tree )
-                menu->addAction( qtr(I_POP_ADD), this, SLOT( popupAddNode() ) );
-        if( index.isValid() )
-        {
-            menu->addSeparator();
-            menu->addAction( qtr( I_POP_EXPLORE ), this, SLOT( popupExplore() ) );
-        }
-        menu->popup( point );
+    current_selection = list;
+    QMenu *menu = new QMenu;
+    if( i_popup_item > -1 )
+    {
+        menu->addAction( qtr(I_POP_PLAY), this, SLOT( popupPlay() ) );
+        menu->addAction( qtr(I_POP_DEL), this, SLOT( popupDel() ) );
+        menu->addSeparator();
+        menu->addAction( qtr(I_POP_STREAM), this, SLOT( popupStream() ) );
+        menu->addAction( qtr(I_POP_SAVE), this, SLOT( popupSave() ) );
+        menu->addSeparator();
+        menu->addAction( qtr(I_POP_INFO), this, SLOT( popupInfo() ) );
+        menu->addSeparator();
+        QMenu *sort_menu = menu->addMenu( qtr( "Sort by ") +
+            qfu( psz_column_title( metaColumn( index.column() ) ) ) );
+        sort_menu->addAction( qtr( "Ascending" ),
+            this, SLOT( popupSortAsc() ) );
+        sort_menu->addAction( qtr( "Descending" ),
+            this, SLOT( popupSortDesc() ) );
     }
-    else
-        PL_UNLOCK;
+    if( tree )
+        menu->addAction( qtr(I_POP_ADD), this, SLOT( popupAddNode() ) );
+    if( i_popup_item > -1 )
+    {
+        menu->addSeparator();
+        menu->addAction( qtr( I_POP_EXPLORE ), this, SLOT( popupExplore() ) );
+    }
+    menu->popup( point );
 }
 
 
@@ -1010,28 +1009,27 @@ void PLModel::viewchanged( int meta )
             _meta >>= 1;
         }
 
-        /* UNUSED        emit layoutAboutToBeChanged(); */
         index = __MIN( index, columnCount() );
         QModelIndex parent = createIndex( 0, 0, rootItem );
 
         if( i_showflags & meta )
             /* Removing columns */
         {
-            emit beginRemoveColumns( parent, index, index+1 );
+            beginRemoveColumns( parent, index, index+1 );
             i_showflags &= ~( meta );
             getSettings()->setValue( "qt-pl-showflags", i_showflags );
-            emit endRemoveColumns();
+            endRemoveColumns();
         }
         else
         {
             /* Adding columns */
-            emit beginInsertColumns( parent, index, index+1 );
+            beginInsertColumns( parent, index, index+1 );
             i_showflags |= meta;
             getSettings()->setValue( "qt-pl-showflags", i_showflags );
-            emit endInsertColumns();
+            endInsertColumns();
         }
+
         emit columnsChanged( meta );
-        rebuild();
     }
 }
 
@@ -1130,13 +1128,23 @@ void PLModel::popupAddNode()
     if( !ok || name.isEmpty() ) return;
     PL_LOCK;
     playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
-                                                    i_popup_item );
+                                                    i_popup_parent );
     if( p_item )
     {
         playlist_NodeCreate( p_playlist, qtu( name ), p_item, 0, NULL );
     }
     PL_UNLOCK;
 }
+
+void PLModel::popupSortAsc()
+{
+    sort( i_popup_parent, i_popup_column, Qt::AscendingOrder );
+}
+
+void PLModel::popupSortDesc()
+{
+    sort( i_popup_parent, i_popup_column, Qt::DescendingOrder );
+}
 /**********************************************************************
  * Playlist callbacks
  **********************************************************************/