Commit e3c255e6 authored by Jakob Leben's avatar Jakob Leben

Qt: drag-and-drop: simplification and robustness

- Make PlMimeData simply a subclass of QMimeData: destructor of indirect
subclasses of QObject is called even if their direct base class' destructor
is not virtual.
- Protection against using input_item_t* from another VLC instance:
qobject_cast<PlMimeData*>() will fail on QMimeData dropped from another process.
- Some refactoring of PLModel::dropMove() for robustness.
parent 066b059b
...@@ -182,14 +182,15 @@ QMimeData *PLModel::mimeData( const QModelIndexList &indexes ) const ...@@ -182,14 +182,15 @@ QMimeData *PLModel::mimeData( const QModelIndexList &indexes ) const
plMimeData->appendItem( item->p_input ); plMimeData->appendItem( item->p_input );
} }
return plMimeData->mimeData(); return plMimeData;
} }
/* Drop operation */ /* Drop operation */
bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action, bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action,
int row, int column, const QModelIndex &parent ) int row, int column, const QModelIndex &parent )
{ {
if( data->hasFormat( "vlc/qt-input-items" ) ) const PlMimeData *plMimeData = qobject_cast<const PlMimeData*>( data );
if( plMimeData )
{ {
if( action == Qt::IgnoreAction ) if( action == Qt::IgnoreAction )
return true; return true;
...@@ -216,14 +217,14 @@ bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action, ...@@ -216,14 +217,14 @@ bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action,
PL_UNLOCK; PL_UNLOCK;
if( copy ) if( copy )
dropAppendCopy( data, getItem( parent ) ); dropAppendCopy( plMimeData, getItem( parent ) );
else else
dropMove( data, getItem( parent ), row ); dropMove( plMimeData, getItem( parent ), row );
} }
return true; return true;
} }
void PLModel::dropAppendCopy( const QMimeData *data, PLItem *target ) void PLModel::dropAppendCopy( const PlMimeData *plMimeData, PLItem *target )
{ {
PL_LOCK; PL_LOCK;
...@@ -234,7 +235,7 @@ void PLModel::dropAppendCopy( const QMimeData *data, PLItem *target ) ...@@ -234,7 +235,7 @@ void PLModel::dropAppendCopy( const QMimeData *data, PLItem *target )
bool b_flat = p_parent == p_playlist->p_playing && bool b_flat = p_parent == p_playlist->p_playing &&
!var_InheritBool( p_intf, "playlist-tree" ); !var_InheritBool( p_intf, "playlist-tree" );
QList<input_item_t*> inputItems = PlMimeData::inputItems( data ); QList<input_item_t*> inputItems = plMimeData->inputItems();
foreach( input_item_t* p_input, inputItems ) foreach( input_item_t* p_input, inputItems )
{ {
playlist_item_t *p_item = playlist_ItemGetByInput( p_playlist, p_input ); playlist_item_t *p_item = playlist_ItemGetByInput( p_playlist, p_input );
...@@ -274,15 +275,31 @@ void PLModel::recursiveAppendCopy( playlist_t *p_playlist, playlist_item_t *sour ...@@ -274,15 +275,31 @@ void PLModel::recursiveAppendCopy( playlist_t *p_playlist, playlist_item_t *sour
recursiveAppendCopy( p_playlist, source->pp_children[i], target, b_flat ); recursiveAppendCopy( p_playlist, source->pp_children[i], target, b_flat );
} }
void PLModel::dropMove( const QMimeData * mimeData, PLItem *target, int row ) void PLModel::dropMove( const PlMimeData * plMimeData, PLItem *target, int row )
{ {
QList<input_item_t*> inputItems = PlMimeData::inputItems( mimeData ); QList<input_item_t*> inputItems = plMimeData->inputItems();
QList<PLItem*> model_items; 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 model_pos = new_pos;
int i = 0;
foreach( input_item_t *p_input, inputItems ) 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 ); PLItem *item = findByInput( rootItem, p_input->i_id );
if( !item ) continue; if( !item ) continue;
...@@ -292,7 +309,10 @@ void PLModel::dropMove( const QMimeData * mimeData, PLItem *target, int row ) ...@@ -292,7 +309,10 @@ void PLModel::dropMove( const QMimeData * mimeData, PLItem *target, int row )
PLItem *climber = target; PLItem *climber = target;
while( climber ) while( climber )
{ {
if( climber == item ) return; if( climber == item )
{
PL_UNLOCK; return;
}
climber = climber->parentItem; climber = climber->parentItem;
} }
...@@ -301,33 +321,21 @@ void PLModel::dropMove( const QMimeData * mimeData, PLItem *target, int row ) ...@@ -301,33 +321,21 @@ void PLModel::dropMove( const QMimeData * mimeData, PLItem *target, int row )
model_pos--; model_pos--;
model_items.append( item ); 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 ) playlist_TreeMoveMany( p_playlist, i, pp_items, p_parent, new_pos );
takeItem( item );
playlist_item_t *pp_items[model_items.size()]; PL_UNLOCK;
PL_LOCK;
int i = 0;
foreach( PLItem *item, model_items ) foreach( PLItem *item, model_items )
{ takeItem( item );
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;
insertChildren( target, model_items, model_pos ); insertChildren( target, model_items, model_pos );
} }
...@@ -1136,10 +1144,7 @@ void PLModel::popupSort( int column ) ...@@ -1136,10 +1144,7 @@ void PLModel::popupSort( int column )
/******************* Drag and Drop helper class ******************/ /******************* Drag and Drop helper class ******************/
PlMimeData::PlMimeData( ) PlMimeData::PlMimeData( )
{ { }
_mimeData = new QMimeData;
setParent( _mimeData );
}
PlMimeData::~PlMimeData() PlMimeData::~PlMimeData()
{ {
...@@ -1153,31 +1158,14 @@ void PlMimeData::appendItem( input_item_t *p_item ) ...@@ -1153,31 +1158,14 @@ void PlMimeData::appendItem( input_item_t *p_item )
_inputItems.append( p_item ); _inputItems.append( p_item );
} }
QMimeData * PlMimeData::mimeData() QList<input_item_t*> PlMimeData::inputItems() const
{ {
QByteArray encodedData; return _inputItems;
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;
} }
QList<input_item_t*> PlMimeData::inputItems( const QMimeData * mimeData ) QStringList PlMimeData::formats () const
{ {
QList<input_item_t*> list; QStringList fmts;
fmts << "vlc/qt-input-items";
if( !mimeData->hasFormat( "vlc/qt-input-items" ) ) return list; return fmts;
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;
} }
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
class PLItem; class PLItem;
class PLSelector; class PLSelector;
class PlMimeData;
class PLModel : public QAbstractItemModel class PLModel : public QAbstractItemModel
{ {
...@@ -142,8 +143,8 @@ private: ...@@ -142,8 +143,8 @@ private:
/* Deep actions (affect core playlist) */ /* Deep actions (affect core playlist) */
static void recursiveAppendCopy( playlist_t *, playlist_item_t *, playlist_item_t *, bool ); static void recursiveAppendCopy( playlist_t *, playlist_item_t *, playlist_item_t *, bool );
void dropAppendCopy( const QMimeData * data, PLItem *target ); void dropAppendCopy( const PlMimeData * data, PLItem *target );
void dropMove( const QMimeData * data, PLItem *target, int new_pos ); void dropMove( const PlMimeData * data, PLItem *target, int new_pos );
/* Popup */ /* Popup */
int i_popup_item, i_popup_parent, i_popup_column; int i_popup_item, i_popup_parent, i_popup_column;
...@@ -177,14 +178,16 @@ private slots: ...@@ -177,14 +178,16 @@ private slots:
void processItemAppend( int item, int parent ); void processItemAppend( int item, int parent );
}; };
class PlMimeData : public QObject class PlMimeData : public QMimeData
{ {
Q_OBJECT;
public: public:
PlMimeData(); PlMimeData();
~PlMimeData(); ~PlMimeData();
void appendItem( input_item_t *p_item ); void appendItem( input_item_t *p_item );
QMimeData *mimeData(); QList<input_item_t*> inputItems() const;
static QList<input_item_t*> inputItems( const QMimeData * mimeData ); QStringList formats () const;
private: private:
QList<input_item_t*> _inputItems; QList<input_item_t*> _inputItems;
......
...@@ -350,7 +350,10 @@ bool PLSelector::dropMimeData ( QTreeWidgetItem * parent, int index, ...@@ -350,7 +350,10 @@ bool PLSelector::dropMimeData ( QTreeWidgetItem * parent, int index,
if( i_truth != IS_PL && i_truth != IS_ML ) return false; if( i_truth != IS_PL && i_truth != IS_ML ) return false;
bool to_pl = ( i_truth == IS_PL ); bool to_pl = ( i_truth == IS_PL );
QList<input_item_t*> inputItems = PlMimeData::inputItems( data ); const PlMimeData *plMimeData = qobject_cast<const PlMimeData*>( data );
if( !plMimeData ) return false;
QList<input_item_t*> inputItems = plMimeData->inputItems();
playlist_Lock( THEPL ); playlist_Lock( THEPL );
......
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