]> git.sesse.net Git - vlc/blobdiff - modules/gui/qt4/components/playlist/playlist_model.cpp
Qt4: cache currentItem index
[vlc] / modules / gui / qt4 / components / playlist / playlist_model.cpp
index 33d3e0f1e856bcfe6323f2f6dbf361855473c799..756ee00d0f86eba2b02282b15dd5eb491249fbdc 100644 (file)
@@ -73,6 +73,7 @@ PLModel::PLModel( playlist_t *_p_playlist,  /* THEPL */
     i_cached_input_id = -1;
     i_popup_item      = i_popup_parent = -1;
     sortingMenu       = NULL;
+    current_index     = QModelIndex();
 
     rootItem          = NULL; /* PLItem rootItem, will be set in rebuild( ) */
 
@@ -98,6 +99,8 @@ PLModel::PLModel( playlist_t *_p_playlist,  /* THEPL */
              this, processItemAppend( int, int ) );
     CONNECT( THEMIM, playlistItemRemoved( int ),
              this, processItemRemoval( int ) );
+    CONNECT( this, currentChanged( const QModelIndex &) ,
+             this, cacheCurrent( const QModelIndex &) );
 }
 
 PLModel::~PLModel()
@@ -108,7 +111,7 @@ PLModel::~PLModel()
 
 Qt::DropActions PLModel::supportedDropActions() const
 {
-    return Qt::CopyAction; /* Why not Qt::MoveAction */
+    return Qt::CopyAction | Qt::MoveAction;
 }
 
 Qt::ItemFlags PLModel::flags( const QModelIndex &index ) const
@@ -182,48 +185,29 @@ QMimeData *PLModel::mimeData( const QModelIndexList &indexes ) const
         plMimeData->appendItem( item->p_input );
     }
 
-    return plMimeData->mimeData();
+    return plMimeData;
 }
 
 /* Drop operation */
 bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action,
                            int row, int column, const QModelIndex &parent )
 {
-    if( data->hasFormat( "vlc/qt-input-items" ) )
-    {
-        if( action == Qt::IgnoreAction )
-            return true;
-
-        PL_LOCK;
-        playlist_item_t *p_parent =
-            playlist_ItemGetById( p_playlist, itemId( parent ) );
-        if( !p_parent || p_parent->i_children == -1 )
-        {
-            PL_UNLOCK;
-            return false;
-        }
-
-        bool copy = false;
-        playlist_item_t *p_pl = p_playlist->p_playing;
-        playlist_item_t *p_ml = p_playlist->p_media_library;
-        if
-        (
-            row == -1 && (
-            ( p_pl && p_parent == p_pl ) ||
-            ( p_ml && p_parent == p_ml ) )
-        )
-            copy = true;
-        PL_UNLOCK;
+    bool copy = action == Qt::CopyAction;
+    if( !copy && action != Qt::MoveAction )
+        return true;
 
+    const PlMimeData *plMimeData = qobject_cast<const PlMimeData*>( data );
+    if( plMimeData )
+    {
         if( copy )
-            dropAppendCopy( data, getItem( parent ) );
+            dropAppendCopy( plMimeData, getItem( parent ), row );
         else
-            dropMove( data, getItem( parent ), row );
+            dropMove( plMimeData, getItem( parent ), row );
     }
     return true;
 }
 
-void PLModel::dropAppendCopy( const QMimeData *data, PLItem *target )
+void PLModel::dropAppendCopy( const PlMimeData *plMimeData, PLItem *target, int pos )
 {
     PL_LOCK;
 
@@ -231,58 +215,45 @@ void PLModel::dropAppendCopy( const QMimeData *data, PLItem *target )
             playlist_ItemGetByInput( p_playlist, target->p_input );
     if( !p_parent ) return;
 
-    bool b_flat = p_parent == p_playlist->p_playing &&
-                  !var_InheritBool( p_intf, "playlist-tree" );
+    if( pos == -1 ) pos = PLAYLIST_END;
+
+    QList<input_item_t*> inputItems = plMimeData->inputItems();
 
-    QList<input_item_t*> inputItems = PlMimeData::inputItems( data );
     foreach( input_item_t* p_input, inputItems )
     {
         playlist_item_t *p_item = playlist_ItemGetByInput( p_playlist, p_input );
         if( !p_item ) continue;
-
-        recursiveAppendCopy( p_playlist, p_item, p_parent, b_flat );
+        pos = playlist_NodeAddCopy( p_playlist, p_item, p_parent, pos );
     }
 
     PL_UNLOCK;
 }
 
-/* Must be entered WITH playlist lock! */
-void PLModel::recursiveAppendCopy( playlist_t *p_playlist, playlist_item_t *source,
-                                   playlist_item_t *target, bool b_flat )
+void PLModel::dropMove( const PlMimeData * plMimeData, PLItem *target, int row )
 {
-    input_item_t *srcInput = source->p_input;
+    QList<input_item_t*> inputItems = plMimeData->inputItems();
+    QList<PLItem*> model_items;
+    playlist_item_t *pp_items[inputItems.size()];
+
+    PL_LOCK;
+
+    playlist_item_t *p_parent =
+        playlist_ItemGetByInput( p_playlist, target->p_input );
 
-    if( !(source->i_children != -1 && b_flat) )
+    if( !p_parent || row > p_parent->i_children )
     {
-        vlc_mutex_lock( &srcInput->lock );
-        input_item_t *newInput =
-            input_item_NewWithType( VLC_OBJECT(p_playlist),
-                                    srcInput->psz_uri, srcInput->psz_name,
-                                    srcInput->i_options, srcInput->ppsz_options,
-                                    srcInput->optflagc, srcInput->i_duration,
-                                    srcInput->i_type );
-        vlc_mutex_unlock( &srcInput->lock );
-
-        if( source->i_children != -1 )
-            target = playlist_NodeCreate( p_playlist, newInput->psz_name, target, 0, newInput );
-        else
-            playlist_NodeAddInput( p_playlist, newInput, target,
-                                   PLAYLIST_APPEND | PLAYLIST_SPREPARSE,
-                                   PLAYLIST_END, pl_Locked );
+        PL_UNLOCK; return;
     }
-    for( int i = 0; i < source->i_children; i++ )
-        recursiveAppendCopy( p_playlist, source->pp_children[i], target, b_flat );
-}
 
-void PLModel::dropMove( const QMimeData * mimeData, PLItem *target, int row )
-{
-    QList<input_item_t*> inputItems = PlMimeData::inputItems( mimeData );
-    QList<PLItem*> model_items;
-    int new_pos = row == -1 ? target->children.size() : row;
+    int new_pos = row == -1 ? p_parent->i_children : row;
     int model_pos = new_pos;
+    int i = 0;
 
     foreach( input_item_t *p_input, inputItems )
     {
+        playlist_item_t *p_item = playlist_ItemGetByInput( p_playlist, p_input );
+        if( !p_item ) continue;
+
         PLItem *item = findByInput( rootItem, p_input->i_id );
         if( !item ) continue;
 
@@ -292,7 +263,10 @@ void PLModel::dropMove( const QMimeData * mimeData, PLItem *target, int row )
         PLItem *climber = target;
         while( climber )
         {
-            if( climber == item ) return;
+            if( climber == item )
+            {
+                PL_UNLOCK; return;
+            }
             climber = climber->parentItem;
         }
 
@@ -301,33 +275,21 @@ void PLModel::dropMove( const QMimeData * mimeData, PLItem *target, int row )
                 model_pos--;
 
         model_items.append( item );
+        pp_items[i] = p_item;
+        i++;
     }
 
-    if( model_items.isEmpty() ) return;
+    if( model_items.isEmpty() )
+    {
+        PL_UNLOCK; return;
+    }
 
-    foreach( PLItem *item, model_items )
-        takeItem( item );
+    playlist_TreeMoveMany( p_playlist, i, pp_items, p_parent, new_pos );
 
-    playlist_item_t *pp_items[model_items.size()];
+    PL_UNLOCK;
 
-    PL_LOCK;
-    int i = 0;
     foreach( PLItem *item, model_items )
-    {
-        playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id );
-        if( !p_item )
-        {
-            PL_UNLOCK;
-            return;
-        }
-        pp_items[i] = p_item;
-        i++;
-    }
-    playlist_item_t *p_parent =
-        playlist_ItemGetById( p_playlist, target->i_id );
-    playlist_TreeMoveMany( p_playlist, i, pp_items, p_parent,
-        new_pos );
-    PL_UNLOCK;
+        takeItem( item );
 
     insertChildren( target, model_items, model_pos );
 }
@@ -421,7 +383,7 @@ QVariant PLModel::data( const QModelIndex &index, int role ) const
 
 bool PLModel::isCurrent( const QModelIndex &index ) const
 {
-    return getItem( index )->p_input == THEMIM->currentInputItem();
+    return index == current_index;
 }
 
 int PLModel::itemId( const QModelIndex &index ) const
@@ -470,12 +432,14 @@ QModelIndex PLModel::index( PLItem *item, int column ) const
     return QModelIndex();
 }
 
+void PLModel::cacheCurrent( const QModelIndex &current )
+{
+    current_index = current;
+}
+
 QModelIndex PLModel::currentIndex()
 {
-    input_thread_t *p_input_thread = THEMIM->getInput();
-    if( !p_input_thread ) return QModelIndex();
-    PLItem *item = findByInput( rootItem, input_GetItem( p_input_thread )->i_id );
-    return index( item, 0 );
+    return current_index;
 }
 
 QModelIndex PLModel::parent( const QModelIndex &index ) const
@@ -820,10 +784,8 @@ void PLModel::updateTreeItem( PLItem *item )
 /************************* Actions ******************************/
 
 /**
- * Deletion, here we have to do a ugly slow hack as we retrieve the full
- * list of indexes to delete at once: when we delete a node and all of
- * its children, we need to update the list.
- * Todo: investigate whethere we can use ranges to be sure to delete all items?
+ * Deletion, don't delete items childrens if item is going to be
+ * delete allready, so we remove childrens from selection-list.
  */
 void PLModel::doDelete( QModelIndexList selected )
 {
@@ -905,6 +867,15 @@ void PLModel::sort( int i_root_id, int column, Qt::SortOrder order )
         endInsertRows( );
     }
     PL_UNLOCK;
+    /* if we have popup item, try to make sure that you keep that item visible */
+    if( i_popup_item > -1 )
+    {
+        PLItem *popupitem = findById( rootItem, i_popup_item );
+        if( popupitem ) emit currentChanged( index( popupitem, 0 ) );
+        /* reset i_popup_item as we don't show it as selected anymore anyway */
+        i_popup_item = -1;
+    }
+    else if( currentIndex().isValid() ) emit currentChanged( currentIndex() );
 }
 
 void PLModel::search( const QString& search_text, const QModelIndex & idx, bool b_recursive )
@@ -1121,7 +1092,7 @@ void PLModel::popupAddNode()
                                                     i_popup_parent );
     if( p_item )
     {
-        playlist_NodeCreate( p_playlist, qtu( name ), p_item, 0, NULL );
+        playlist_NodeCreate( p_playlist, qtu( name ), p_item, PLAYLIST_END, 0, NULL );
     }
     PL_UNLOCK;
 }
@@ -1136,10 +1107,7 @@ void PLModel::popupSort( int column )
 /******************* Drag and Drop helper class ******************/
 
 PlMimeData::PlMimeData( )
-{
-    _mimeData = new QMimeData;
-    setParent( _mimeData );
-}
+{ }
 
 PlMimeData::~PlMimeData()
 {
@@ -1153,31 +1121,14 @@ void PlMimeData::appendItem( input_item_t *p_item )
     _inputItems.append( p_item );
 }
 
-QMimeData * PlMimeData::mimeData()
+QList<input_item_t*> PlMimeData::inputItems() const
 {
-    QByteArray encodedData;
-    input_item_t *pp_items[_inputItems.size()];
-
-    for( int i = 0; i < _inputItems.size() ; i++ )
-        pp_items[i] = _inputItems[i];
-
-    _mimeData->setData( "vlc/qt-input-items",
-                        QByteArray( (char*) pp_items, _inputItems.size() * sizeof( input_item_t*) ) );
-    return _mimeData;
+    return _inputItems;
 }
 
-QList<input_item_t*> PlMimeData::inputItems( const QMimeData * mimeData )
+QStringList PlMimeData::formats () const
 {
-    QList<input_item_t*> list;
-
-    if( !mimeData->hasFormat( "vlc/qt-input-items" ) ) return list;
-
-    QByteArray encodedData = mimeData->data( "vlc/qt-input-items" );
-
-    input_item_t **pp_items = (input_item_t **) encodedData.data();
-    int i_items = encodedData.size() / sizeof( input_item_t* );
-    for( int i = 0; i < i_items; i++ )
-        list.append( pp_items[i] );
-
-    return list;
+    QStringList fmts;
+    fmts << "vlc/qt-input-items";
+    return fmts;
 }