]> git.sesse.net Git - vlc/blobdiff - modules/gui/qt4/components/playlist/playlist_model.cpp
Qt: drag-and-drop: simplification and robustness
[vlc] / modules / gui / qt4 / components / playlist / playlist_model.cpp
index 09785fc5feff70b5a385b3a2e97be9c33e797249..82b3178be6c8c118d073b9a3c3476055cf7395bf 100644 (file)
@@ -137,7 +137,7 @@ Qt::ItemFlags PLModel::flags( const QModelIndex &index ) const
 QStringList PLModel::mimeTypes() const
 {
     QStringList types;
-    types << "vlc/qt-playlist-item";
+    types << "vlc/qt-input-items";
     return types;
 }
 
@@ -152,9 +152,7 @@ bool modelIndexLessThen( const QModelIndex &i1, const QModelIndex &i2 )
 
 QMimeData *PLModel::mimeData( const QModelIndexList &indexes ) const
 {
-    QMimeData *mimeData = new QMimeData();
-    QByteArray encodedData;
-    QDataStream stream( &encodedData, QIODevice::WriteOnly );
+    PlMimeData *plMimeData = new PlMimeData();
     QModelIndexList list;
 
     foreach( const QModelIndex &index, indexes ) {
@@ -181,17 +179,18 @@ QMimeData *PLModel::mimeData( const QModelIndexList &indexes ) const
         else
             item = getItem( index );
 
-        stream << item->id();
+        plMimeData->appendItem( item->p_input );
     }
-    mimeData->setData( "vlc/qt-playlist-item", encodedData );
-    return 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-playlist-item" ) )
+    const PlMimeData *plMimeData = qobject_cast<const PlMimeData*>( data );
+    if( plMimeData )
     {
         if( action == Qt::IgnoreAction )
             return true;
@@ -217,36 +216,34 @@ bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action,
             copy = true;
         PL_UNLOCK;
 
-        QByteArray encodedData = data->data( "vlc/qt-playlist-item" );
         if( copy )
-            dropAppendCopy( encodedData, getItem( parent ) );
+            dropAppendCopy( plMimeData, getItem( parent ) );
         else
-            dropMove( encodedData, getItem( parent ), row );
+            dropMove( plMimeData, getItem( parent ), row );
     }
     return true;
 }
 
-void PLModel::dropAppendCopy( QByteArray& data, PLItem *target )
+void PLModel::dropAppendCopy( const PlMimeData *plMimeData, PLItem *target )
 {
-    QDataStream stream( &data, QIODevice::ReadOnly );
-
     PL_LOCK;
+
     playlist_item_t *p_parent =
-            playlist_ItemGetById( p_playlist, target->i_id );
+            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" );
 
-    while( !stream.atEnd() )
+    QList<input_item_t*> inputItems = plMimeData->inputItems();
+    foreach( input_item_t* p_input, inputItems )
     {
-        int i_id;
-        stream >> i_id;
-        playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id );
+        playlist_item_t *p_item = playlist_ItemGetByInput( p_playlist, p_input );
         if( !p_item ) continue;
 
         recursiveAppendCopy( p_playlist, p_item, p_parent, b_flat );
     }
+
     PL_UNLOCK;
 }
 
@@ -278,18 +275,32 @@ void PLModel::recursiveAppendCopy( playlist_t *p_playlist, playlist_item_t *sour
         recursiveAppendCopy( p_playlist, source->pp_children[i], target, b_flat );
 }
 
-void PLModel::dropMove( QByteArray& data, PLItem *target, int row )
+void PLModel::dropMove( const PlMimeData * plMimeData, PLItem *target, int row )
 {
-    QDataStream stream( &data, QIODevice::ReadOnly );
+    QList<input_item_t*> inputItems = plMimeData->inputItems();
     QList<PLItem*> model_items;
-    int new_pos = row == -1 ? target->children.size() : row;
+    playlist_item_t *pp_items[inputItems.size()];
+
+    PL_LOCK;
+
+    playlist_item_t *p_parent =
+        playlist_ItemGetByInput( p_playlist, target->p_input );
+
+    if( !p_parent || row > p_parent->i_children )
+    {
+        PL_UNLOCK; return;
+    }
+
+    int new_pos = row == -1 ? p_parent->i_children : row;
     int model_pos = new_pos;
+    int i = 0;
 
-    while( !stream.atEnd() )
+    foreach( input_item_t *p_input, inputItems )
     {
-        int i_id;
-        stream >> i_id;
-        PLItem *item = findById( rootItem, i_id );
+        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;
 
         /* Better not try to move a node into itself.
@@ -298,7 +309,10 @@ void PLModel::dropMove( QByteArray& data, PLItem *target, int row )
         PLItem *climber = target;
         while( climber )
         {
-            if( climber == item ) return;
+            if( climber == item )
+            {
+                PL_UNLOCK; return;
+            }
             climber = climber->parentItem;
         }
 
@@ -307,33 +321,21 @@ void PLModel::dropMove( QByteArray& data, 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 );
 }
@@ -1104,7 +1106,7 @@ void PLModel::popupExplore()
                    !strncasecmp( psz_access, "file", 4 ) ||
                    !strncasecmp( psz_access, "dire", 4 ) ))
            {
-               QFileInfo info( qfu( psz_path ) );
+               QFileInfo info( qfu( decode_URI( psz_path ) ) );
                QDesktopServices::openUrl(
                                QUrl::fromLocalFile( info.absolutePath() ) );
            }
@@ -1138,3 +1140,32 @@ void PLModel::popupSort( int column )
           column > 0 ? column - 1 : -column - 1,
           column > 0 ? Qt::AscendingOrder : Qt::DescendingOrder );
 }
+
+/******************* Drag and Drop helper class ******************/
+
+PlMimeData::PlMimeData( )
+{ }
+
+PlMimeData::~PlMimeData()
+{
+    foreach( input_item_t *p_item, _inputItems )
+        vlc_gc_decref( p_item );
+}
+
+void PlMimeData::appendItem( input_item_t *p_item )
+{
+    vlc_gc_incref( p_item );
+    _inputItems.append( p_item );
+}
+
+QList<input_item_t*> PlMimeData::inputItems() const
+{
+    return _inputItems;
+}
+
+QStringList PlMimeData::formats () const
+{
+    QStringList fmts;
+    fmts << "vlc/qt-input-items";
+    return fmts;
+}