/*****************************************************************************
* playlist_model.cpp : Manage playlist model
****************************************************************************
- * Copyright (C) 2006-2007 the VideoLAN team
+ * Copyright (C) 2006-2011 the VideoLAN team
* $Id$
*
* Authors: Clément Stenac <zorglub@videolan.org>
#endif
#include "qt4.hpp"
-#include "dialogs_provider.hpp"
#include "components/playlist/playlist_model.hpp"
-#include "dialogs/mediainfo.hpp"
-#include "dialogs/playlist.hpp"
-#include <vlc_intf_strings.h>
+#include "dialogs_provider.hpp" /* THEDP */
+#include "input_manager.hpp" /* THEMIM */
+#include "dialogs/mediainfo.hpp" /* MediaInfo Dialog */
+#include "dialogs/playlist.hpp" /* Playlist Dialog */
+
+#include <vlc_intf_strings.h> /* I_DIR */
#include "pixmaps/types/type_unknown.xpm"
+#include "sorting.h"
#include <assert.h>
#include <QIcon>
#include <QFont>
#include <QMenu>
-#include <QApplication>
-#include <QSettings>
#include <QUrl>
#include <QFileInfo>
#include <QDesktopServices>
#include <QInputDialog>
-
-#include "sorting.h"
+#include <QSignalMapper>
#define I_NEW_DIR \
I_DIR_OR_FOLDER( N_("Create Directory"), N_( "Create Folder" ) )
intf_thread_t *_p_intf, /* main Qt p_intf */
playlist_item_t * p_root,
QObject *parent ) /* Basic Qt parent */
- : QAbstractItemModel( parent )
+ : VLCModel( _p_intf, parent )
{
- p_intf = _p_intf;
p_playlist = _p_playlist;
i_cached_id = -1;
i_cached_input_id = -1;
ADD_ICON( NODE, ":/type/node" );
#undef ADD_ICON
+ i_zoom = getSettings()->value( "Playlist/zoom", 0 ).toInt();
+
rebuild( p_root );
DCONNECT( THEMIM->getIM(), metaChanged( input_item_t *),
- this, processInputItemUpdate( input_item_t *) );
+ this, processInputItemUpdate( input_item_t *) );
DCONNECT( THEMIM, inputChanged( input_thread_t * ),
- this, processInputItemUpdate( input_thread_t* ) );
+ this, processInputItemUpdate( input_thread_t* ) );
CONNECT( THEMIM, playlistItemAppended( int, int ),
this, processItemAppend( int, int ) );
CONNECT( THEMIM, playlistItemRemoved( int ),
PLModel::~PLModel()
{
+ getSettings()->setValue( "Playlist/zoom", i_zoom );
delete rootItem;
delete sortingMenu;
}
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
{
Qt::ItemFlags flags = QAbstractItemModel::flags( index );
- PLItem *item = index.isValid() ? getItem( index ) : rootItem;
+ const PLItem *item = index.isValid() ? getItem( index ) : rootItem;
if( canEdit() )
{
QStringList PLModel::mimeTypes() const
{
QStringList types;
- types << "vlc/qt-playlist-item";
+ types << "vlc/qt-input-items";
return types;
}
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 ) {
else
item = getItem( index );
- stream << item->id();
+ plMimeData->appendItem( item->inputItem() );
}
- 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 )
+ int row, int, const QModelIndex &parent )
{
- if( data->hasFormat( "vlc/qt-playlist-item" ) )
- {
- 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 = action == Qt::CopyAction;
+ if( !copy && action != Qt::MoveAction )
+ return true;
- 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;
-
- QByteArray encodedData = data->data( "vlc/qt-playlist-item" );
+ const PlMimeData *plMimeData = qobject_cast<const PlMimeData*>( data );
+ if( plMimeData )
+ {
if( copy )
- dropAppendCopy( encodedData, getItem( parent ) );
+ dropAppendCopy( plMimeData, getItem( parent ), row );
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, int pos )
{
- QDataStream stream( &data, QIODevice::ReadOnly );
-
PL_LOCK;
+
playlist_item_t *p_parent =
- playlist_ItemGetById( p_playlist, target->i_id );
+ playlist_ItemGetByInput( p_playlist, target->inputItem() );
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();
- while( !stream.atEnd() )
+ 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 );
+ 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.count()];
+
+ PL_LOCK;
- if( !(source->i_children != -1 && b_flat) )
+ playlist_item_t *p_parent =
+ playlist_ItemGetByInput( p_playlist, target->inputItem() );
+
+ 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( QByteArray& data, PLItem *target, int row )
-{
- QDataStream stream( &data, QIODevice::ReadOnly );
- 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;
- 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.
PLItem *climber = target;
while( climber )
{
- if( climber == item ) return;
- climber = climber->parentItem;
+ if( climber == item )
+ {
+ PL_UNLOCK; return;
+ }
+ climber = climber->parent();
}
- if( item->parentItem == target &&
+ if( item->parent() == target &&
target->children.indexOf( item ) < new_pos )
- model_pos--;
+ 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 );
}
void PLModel::activateItem( const QModelIndex &index )
{
assert( index.isValid() );
- PLItem *item = getItem( index );
+ const PLItem *item = getItem( index );
assert( item );
PL_LOCK;
playlist_item_t *p_item = playlist_ItemGetById( p_playlist, item->i_id );
PL_UNLOCK;
}
-/* Must be entered with lock */
+/* Convenient overloaded private version of activateItem
+ * Must be entered with PL lock */
void PLModel::activateItem( playlist_item_t *p_item )
{
if( !p_item ) return;
playlist_item_t *p_parent = p_item;
while( p_parent )
{
- if( p_parent->i_id == rootItem->i_id ) break;
+ if( p_parent->i_id == rootItem->id() ) break;
p_parent = p_parent->p_parent;
}
if( p_parent )
playlist_Control( p_playlist, PLAYLIST_VIEWPLAY, pl_Locked,
- p_parent, p_item );
+ p_parent, p_item );
}
/****************** Base model mandatory implementations *****************/
-QVariant PLModel::data( const QModelIndex &index, int role ) const
+QVariant PLModel::data( const QModelIndex &index, const int role ) const
{
if( !index.isValid() ) return QVariant();
- PLItem *item = getItem( index );
+ const PLItem *item = getItem( index );
if( role == Qt::DisplayRole )
{
int metadata = columnToMeta( index.column() );
QString returninfo;
if( metadata == COLUMN_NUMBER )
returninfo = QString::number( index.row() + 1 );
+ else if( metadata == COLUMN_COVER )
+ {
+ QString artUrl;
+ artUrl = InputManager::decodeArtURL( item->inputItem() );
+ if( artUrl.isEmpty() )
+ {
+ for( int i = 0; i < item->childCount(); i++ )
+ {
+ artUrl = InputManager::decodeArtURL( item->child( i )->inputItem() );
+ if( !artUrl.isEmpty() )
+ break;
+ }
+ }
+ return QVariant( artUrl );
+ }
else
{
- char *psz = psz_column_meta( item->p_input, metadata );
+ char *psz = psz_column_meta( item->inputItem(), metadata );
returninfo = qfu( psz );
free( psz );
}
else if( role == Qt::DecorationRole && index.column() == 0 )
{
/* Used to segfault here because i_type wasn't always initialized */
- return QVariant( PLModel::icons[item->p_input->i_type] );
+ return QVariant( PLModel::icons[item->inputItem()->i_type] );
}
else if( role == Qt::FontRole )
{
+ QFont f;
+ f.setPointSize( __MAX( f.pointSize() - 1 + i_zoom, 4 ) );
if( isCurrent( index ) )
- {
- QFont f; f.setBold( true ); return QVariant( f );
- }
+ f.setBold( true );
+ return QVariant( f );
}
else if( role == Qt::BackgroundRole && isCurrent( index ) )
{
return QVariant( QBrush( Qt::gray ) );
}
- else if( role == IsCurrentRole ) return QVariant( isCurrent( index ) );
+ else if( role == IsCurrentRole )
+ {
+ return QVariant( isCurrent( index ) );
+ }
else if( role == IsLeafNodeRole )
{
QVariant isLeaf;
PL_UNLOCK;
return isLeaf;
}
+ else if( role == IsCurrentsParentNodeRole )
+ {
+ return QVariant( isParent( index, currentIndex() ) );
+ }
return QVariant();
}
+/* Seek from current index toward the top and see if index is one of parent nodes */
+bool PLModel::isParent( const QModelIndex &index, const QModelIndex ¤t ) const
+{
+ if( !index.isValid() )
+ return false;
+
+ if( index == current )
+ return true;
+
+ if( !current.isValid() || !current.parent().isValid() )
+ return false;
+
+ return isParent( index, current.parent() );
+}
+
bool PLModel::isCurrent( const QModelIndex &index ) const
{
- return getItem( index )->p_input == THEMIM->currentInputItem();
+ return getItem( index )->inputItem() == THEMIM->currentInputItem();
}
int PLModel::itemId( const QModelIndex &index ) const
{
- return getItem( index )->i_id;
+ return getItem( index )->id();
}
QVariant PLModel::headerData( int section, Qt::Orientation orientation,
return QVariant( qfu( psz_column_title( meta_col ) ) );
}
-QModelIndex PLModel::index( int row, int column, const QModelIndex &parent )
+QModelIndex PLModel::index( const int row, const int column, const QModelIndex &parent )
const
{
PLItem *parentItem = parent.isValid() ? getItem( parent ) : rootItem;
return QModelIndex();
}
-QModelIndex PLModel::index( int i_id, int c )
+QModelIndex PLModel::index( const int i_id, const int c )
{
- return index( findById( rootItem, i_id ), c );
+ return index( findById( rootItem, i_id ), c );
}
/* Return the index of a given item */
return QModelIndex();
}
-QModelIndex PLModel::currentIndex()
+QModelIndex PLModel::currentIndex() const
{
input_thread_t *p_input_thread = THEMIM->getInput();
if( !p_input_thread ) return QModelIndex();
PLItem *parentItem = childItem->parent();
if( !parentItem || parentItem == rootItem ) return QModelIndex();
- if( !parentItem->parentItem )
+ if( !parentItem->parent() )
{
msg_Err( p_playlist, "No parent parent, trying row 0 " );
msg_Err( p_playlist, "----- PLEASE REPORT THIS ------" );
return createIndex( 0, 0, parentItem );
}
- QModelIndex ind = createIndex(parentItem->row(), 0, parentItem);
- return ind;
+ return createIndex(parentItem->row(), 0, parentItem);
}
-int PLModel::columnCount( const QModelIndex &i) const
+int PLModel::columnCount( const QModelIndex &) const
{
return columnFromMeta( COLUMN_END );
}
int PLModel::rowCount( const QModelIndex &parent ) const
{
- PLItem *parentItem = parent.isValid() ? getItem( parent ) : rootItem;
+ const PLItem *parentItem = parent.isValid() ? getItem( parent ) : rootItem;
return parentItem->childCount();
}
QStringList PLModel::selectedURIs()
{
QStringList lst;
- for( int i = 0; i < current_selection.size(); i++ )
+ for( int i = 0; i < current_selection.count(); i++ )
{
- PLItem *item = getItem( current_selection[i] );
+ const PLItem *item = getItem( current_selection[i] );
if( item )
{
PL_LOCK;
return lst;
}
-
/************************* Lookups *****************************/
-
-PLItem *PLModel::findById( PLItem *root, int i_id )
+PLItem *PLModel::findById( PLItem *root, int i_id ) const
{
return findInner( root, i_id, false );
}
-PLItem *PLModel::findByInput( PLItem *root, int i_id )
+PLItem *PLModel::findByInput( PLItem *root, int i_id ) const
{
PLItem *result = findInner( root, i_id, true );
return result;
}
-#define CACHE( i, p ) { i_cached_id = i; p_cached_item = p; }
-#define ICACHE( i, p ) { i_cached_input_id = i; p_cached_item_bi = p; }
-
-PLItem * PLModel::findInner( PLItem *root, int i_id, bool b_input )
+PLItem * PLModel::findInner( PLItem *root, int i_id, bool b_input ) const
{
if( !root ) return NULL;
- if( ( !b_input && i_cached_id == i_id) ||
- ( b_input && i_cached_input_id ==i_id ) )
- {
- return b_input ? p_cached_item_bi : p_cached_item;
- }
- if( !b_input && root->i_id == i_id )
- {
- CACHE( i_id, root );
+ if( !b_input && root->id() == i_id )
return root;
- }
- else if( b_input && root->p_input->i_id == i_id )
- {
- ICACHE( i_id, root );
+
+ else if( b_input && root->inputItem()->i_id == i_id )
return root;
- }
QList<PLItem *>::iterator it = root->children.begin();
while ( it != root->children.end() )
{
- if( !b_input && (*it)->i_id == i_id )
- {
- CACHE( i_id, (*it) );
- return p_cached_item;
- }
- else if( b_input && (*it)->p_input->i_id == i_id )
- {
- ICACHE( i_id, (*it) );
- return p_cached_item_bi;
- }
- if( (*it)->children.size() )
+ if( !b_input && (*it)->id() == i_id )
+ return (*it);
+
+ else if( b_input && (*it)->inputItem()->i_id == i_id )
+ return (*it);
+
+ if( (*it)->childCount() )
{
PLItem *childFound = findInner( (*it), i_id, b_input );
if( childFound )
- {
- if( b_input )
- ICACHE( i_id, childFound )
- else
- CACHE( i_id, childFound )
return childFound;
- }
}
- it++;
+ ++it;
}
return NULL;
}
-#undef CACHE
-#undef ICACHE
-
-int PLModel::columnToMeta( int _column )
-{
- int meta = 1;
- int column = 0;
-
- while( column != _column && meta != COLUMN_END )
- {
- meta <<= 1;
- column++;
- }
-
- return meta;
-}
-
-int PLModel::columnFromMeta( int meta_col )
-{
- int meta = 1;
- int column = 0;
-
- while( meta != meta_col && meta != COLUMN_END )
- {
- meta <<= 1;
- column++;
- }
-
- return column;
-}
bool PLModel::canEdit() const
{
- return (
- rootItem != NULL &&
- (
- rootItem->p_input == p_playlist->p_playing->p_input ||
- (
- p_playlist->p_media_library &&
- rootItem->p_input == p_playlist->p_media_library->p_input
- )
- )
- );
+ return (
+ rootItem != NULL &&
+ (
+ rootItem->inputItem() == p_playlist->p_playing->p_input ||
+ ( p_playlist->p_media_library &&
+ rootItem->inputItem() == p_playlist->p_media_library->p_input )
+ )
+ );
}
+
/************************* Updates handling *****************************/
/**** Events processing ****/
if( p_input && !( p_input->b_dead || !vlc_object_alive( p_input ) ) )
{
PLItem *item = findByInput( rootItem, input_GetItem( p_input )->i_id );
- if( item ) emit currentChanged( index( item, 0 ) );
+ if( item ) emit currentIndexChanged( index( item, 0 ) );
}
processInputItemUpdate( input_GetItem( p_input ) );
}
{
playlist_item_t *p_item = NULL;
PLItem *newItem = NULL;
- input_thread_t *currentInputThread;
int pos;
- PLItem *nodeItem = findById( rootItem, i_parent );
- if( !nodeItem ) return;
+ /* Find the Parent */
+ PLItem *nodeParentItem = findById( rootItem, i_parent );
+ if( !nodeParentItem ) return;
- foreach( PLItem *existing, nodeItem->children )
- if( existing->i_id == i_item ) return;
+ /* Search for an already matching children */
+ foreach( const PLItem *existing, nodeParentItem->children )
+ if( existing->i_id == i_item ) return;
+ /* Find the child */
PL_LOCK;
p_item = playlist_ItemGetById( p_playlist, i_item );
if( !p_item || p_item->i_flags & PLAYLIST_DBL_FLAG )
for( pos = 0; pos < p_item->p_parent->i_children; pos++ )
if( p_item->p_parent->pp_children[pos] == p_item ) break;
- newItem = new PLItem( p_item, nodeItem );
+ newItem = new PLItem( p_item, nodeParentItem );
PL_UNLOCK;
- beginInsertRows( index( nodeItem, 0 ), pos, pos );
- nodeItem->insertChild( newItem, pos );
+ /* We insert the newItem (children) inside the parent */
+ beginInsertRows( index( nodeParentItem, 0 ), pos, pos );
+ nodeParentItem->insertChild( newItem, pos );
endInsertRows();
- if( newItem->p_input == THEMIM->currentInputItem() )
- emit currentChanged( index( newItem, 0 ) );
-}
-
-
-void PLModel::rebuild()
-{
- rebuild( NULL );
+ if( newItem->inputItem() == THEMIM->currentInputItem() )
+ emit currentIndexChanged( index( newItem, 0 ) );
}
void PLModel::rebuild( playlist_item_t *p_root )
{
- playlist_item_t* p_item;
-
/* Invalidate cache */
i_cached_id = i_cached_input_id = -1;
if( rootItem ) rootItem->removeChildren();
PL_LOCK;
- if( p_root )
+ if( p_root ) // Can be NULL
{
delete rootItem;
rootItem = new PLItem( p_root );
void PLModel::takeItem( PLItem *item )
{
assert( item );
- PLItem *parent = item->parentItem;
+ PLItem *parent = item->parent();
assert( parent );
int i_index = parent->children.indexOf( item );
void PLModel::insertChildren( PLItem *node, QList<PLItem*>& items, int i_pos )
{
assert( node );
- int count = items.size();
+ int count = items.count();
if( !count ) return;
+ printf( "Here I am\n");
beginInsertRows( index( node, 0 ), i_pos, i_pos + count - 1 );
for( int i = 0; i < count; i++ )
{
i_cached_id = -1;
i_cached_input_id = -1;
- if( item->parentItem ) {
- int i = item->parentItem->children.indexOf( item );
- beginRemoveRows( index( item->parentItem, 0), i, i );
- item->parentItem->children.removeAt(i);
+ if( item->parent() ) {
+ int i = item->parent()->children.indexOf( item );
+ beginRemoveRows( index( item->parent(), 0), i, i );
+ item->parent()->children.removeAt(i);
delete item;
endRemoveRows();
}
/* This function must be entered WITH the playlist lock */
void PLModel::updateChildren( PLItem *root )
{
- playlist_item_t *p_node = playlist_ItemGetById( p_playlist, root->i_id );
+ playlist_item_t *p_node = playlist_ItemGetById( p_playlist, root->id() );
updateChildren( p_node, root );
}
/************************* 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 )
{
if( index.column() != 0 ) continue;
PLItem *item = getItem( index );
- if( item->children.size() )
+ if( item->childCount() )
recurseDelete( item->children, &selected );
PL_LOCK;
- playlist_DeleteFromInput( p_playlist, item->p_input, pl_Locked );
+ playlist_DeleteFromInput( p_playlist, item->inputItem(), pl_Locked );
PL_UNLOCK;
removeItem( item );
void PLModel::recurseDelete( QList<PLItem*> children, QModelIndexList *fullList )
{
- for( int i = children.size() - 1; i >= 0 ; i-- )
+ for( int i = children.count() - 1; i >= 0 ; i-- )
{
PLItem *item = children[i];
- if( item->children.size() )
+ if( item->childCount() )
recurseDelete( item->children, fullList );
fullList->removeAll( index( item, 0 ) );
}
}
/******* Volume III: Sorting and searching ********/
-void PLModel::sort( int column, Qt::SortOrder order )
+void PLModel::sort( const int column, Qt::SortOrder order )
{
- sort( rootItem->i_id, column, order );
+ sort( rootItem->id(), column, order );
}
-void PLModel::sort( int i_root_id, int column, Qt::SortOrder order )
+void PLModel::sort( const int i_root_id, const int column, Qt::SortOrder order )
{
msg_Dbg( p_intf, "Sorting by column %i, order %i", column, order );
PLItem *item = findById( rootItem, i_root_id );
if( !item ) return;
QModelIndex qIndex = index( item, 0 );
- int count = item->children.size();
+ int count = item->childCount();
if( count )
{
beginRemoveRows( qIndex, 0, count - 1 );
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 currentIndexChanged( 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 currentIndexChanged( currentIndex() );
}
void PLModel::search( const QString& search_text, const QModelIndex & idx, bool b_recursive )
playlist_item_t *p_root = playlist_ItemGetById( p_playlist,
itemId( idx ) );
assert( p_root );
- const char *psz_name = qtu( search_text );
- playlist_LiveSearchUpdate( p_playlist , p_root, psz_name, b_recursive );
-
+ playlist_LiveSearchUpdate( p_playlist , p_root, qtu( search_text ),
+ b_recursive );
if( idx.isValid() )
{
PLItem *searchRoot = getItem( idx );
- beginRemoveRows( idx, 0, searchRoot->children.size() - 1 );
+ beginRemoveRows( idx, 0, searchRoot->childCount() - 1 );
searchRoot->removeChildren();
endRemoveRows( );
- beginInsertRows( idx, 0, searchRoot->children.size() - 1 );
- updateChildren( searchRoot );
+ beginInsertRows( idx, 0, searchRoot->childCount() - 1 );
+ updateChildren( searchRoot ); // The PL_LOCK is needed here
endInsertRows();
PL_UNLOCK;
/*********** Popup *********/
bool PLModel::popup( const QModelIndex & index, const QPoint &point, const QModelIndexList &list )
{
- int i_id = index.isValid() ? itemId( index ) : rootItem->i_id;
+ int i_id = index.isValid() ? itemId( index ) : rootItem->id();
PL_LOCK;
playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_id );
return false;
}
- i_popup_item = index.isValid() ? p_item->i_id : -1;
+ 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 ) :
- ( rootItem->i_id );
- i_popup_column = index.column();
+ ( rootItem->id() );
- bool tree = ( rootItem && rootItem->i_id != p_playlist->p_playing->i_id ) ||
+ bool tree = ( rootItem && rootItem->id() != p_playlist->p_playing->i_id ) ||
var_InheritBool( p_intf, "playlist-tree" );
+ input_item_t *p_input = p_item->p_input;
+ vlc_gc_incref( p_input );
PL_UNLOCK;
- current_selection = list;
-
+ /* */
QMenu menu;
+
+ /* Play/Stream/Info static actions */
if( i_popup_item > -1 )
{
menu.addAction( QIcon( ":/menu/play" ), qtr(I_POP_PLAY), this, SLOT( popupPlay() ) );
qtr(I_POP_STREAM), this, SLOT( popupStream() ) );
menu.addAction( qtr(I_POP_SAVE), this, SLOT( popupSave() ) );
menu.addAction( QIcon( ":/menu/info" ), qtr(I_POP_INFO), this, SLOT( popupInfo() ) );
- menu.addAction( QIcon( ":/type/folder-grey" ),
- qtr( I_POP_EXPLORE ), this, SLOT( popupExplore() ) );
+ if( p_input->psz_uri && !strncasecmp( p_input->psz_uri, "file://", 7 ) )
+ {
+ menu.addAction( QIcon( ":/type/folder-grey" ),
+ qtr( I_POP_EXPLORE ), this, SLOT( popupExplore() ) );
+ }
menu.addSeparator();
}
+ vlc_gc_decref( p_input );
+
+ /* In PL or ML, allow to add a file/folder */
if( canEdit() )
{
QIcon addIcon( ":/buttons/playlist/playlist_add" );
menu.addSeparator();
if( tree ) menu.addAction( addIcon, qtr(I_POP_NEWFOLDER), this, SLOT( popupAddNode() ) );
- if( rootItem->i_id == THEPL->p_playing->i_id )
+ if( rootItem->id() == THEPL->p_playing->i_id )
{
menu.addAction( addIcon, qtr(I_PL_ADDF), THEDP, SLOT( simplePLAppendDialog()) );
menu.addAction( addIcon, qtr(I_PL_ADDDIR), THEDP, SLOT( PLAppendDir()) );
menu.addAction( addIcon, qtr(I_OP_ADVOP), THEDP, SLOT( PLAppendDialog()) );
}
else if( THEPL->p_media_library &&
- rootItem->i_id == THEPL->p_media_library->i_id )
+ rootItem->id() == THEPL->p_media_library->i_id )
{
menu.addAction( addIcon, qtr(I_PL_ADDF), THEDP, SLOT( simpleMLAppendDialog()) );
menu.addAction( addIcon, qtr(I_PL_ADDDIR), THEDP, SLOT( MLAppendDir() ) );
menu.addAction( addIcon, qtr(I_OP_ADVOP), THEDP, SLOT( MLAppendDialog() ) );
}
}
+
+ /* Item removal */
if( i_popup_item > -1 )
{
+ if( rootItem->id() != THEPL->p_playing->i_id )
+ menu.addAction( qtr( "Add to playlist"), this, SLOT( popupAddToPlaylist() ) );
menu.addAction( QIcon( ":/buttons/playlist/playlist_remove" ),
qtr(I_POP_DEL), this, SLOT( popupDel() ) );
- menu.addSeparator();
- if( !sortingMenu )
+ }
+
+ menu.addSeparator();
+ /* Playlist sorting */
+ if( !sortingMenu )
+ {
+ sortingMenu = new QMenu( qtr( "Sort by" ) );
+ sortingMapper = new QSignalMapper( this );
+ /* Choose what columns to show in sorting menu, not sure if this should be configurable*/
+ QList<int> sortingColumns;
+ sortingColumns << COLUMN_TITLE << COLUMN_ARTIST << COLUMN_ALBUM << COLUMN_TRACK_NUMBER << COLUMN_URI;
+ foreach( int Column, sortingColumns )
{
- sortingMenu = new QMenu( qtr( "Sort by" ) );
- sortingMapper = new QSignalMapper( this );
- int i, j;
- for( i = 1, j = 1; i < COLUMN_END; i <<= 1, j++ )
- {
- if( i == COLUMN_NUMBER ) continue;
- QMenu *m = sortingMenu->addMenu( qfu( psz_column_title( i ) ) );
- QAction *asc = m->addAction( qtr("Ascending") );
- QAction *desc = m->addAction( qtr("Descending") );
- sortingMapper->setMapping( asc, j );
- sortingMapper->setMapping( desc, -j );
- CONNECT( asc, triggered(), sortingMapper, map() );
- CONNECT( desc, triggered(), sortingMapper, map() );
- }
- CONNECT( sortingMapper, mapped( int ), this, popupSort( int ) );
+ QAction *asc = sortingMenu->addAction( qfu( psz_column_title( Column ) ) + " " + qtr("Ascending") );
+ QAction *desc = sortingMenu->addAction( qfu( psz_column_title( Column ) ) + " " + qtr("Descending") );
+ sortingMapper->setMapping( asc, columnFromMeta(Column) + 1 );
+ sortingMapper->setMapping( desc, -1 * (columnFromMeta(Column)+1) );
+ CONNECT( asc, triggered(), sortingMapper, map() );
+ CONNECT( desc, triggered(), sortingMapper, map() );
}
- menu.addMenu( sortingMenu );
+ CONNECT( sortingMapper, mapped( int ), this, popupSort( int ) );
}
+ menu.addMenu( sortingMenu );
+
+ /* Zoom */
+ QMenu *zoomMenu = new QMenu( qtr( "Display size" ) );
+ zoomMenu->addAction( qtr( "Increase" ), this, SLOT( increaseZoom() ) );
+ zoomMenu->addAction( qtr( "Decrease" ), this, SLOT( decreaseZoom() ) );
+ menu.addMenu( zoomMenu );
+
+ /* Store the current selected item for popup*() methods */
+ current_selection = list;
+
+ /* Display and forward the result */
if( !menu.isEmpty() )
{
menu.exec( point ); return true;
PL_UNLOCK;
}
+void PLModel::popupAddToPlaylist()
+{
+ playlist_Lock( THEPL );
+
+ foreach( QModelIndex currentIndex, current_selection )
+ {
+ playlist_item_t *p_item = playlist_ItemGetById( THEPL, itemId( currentIndex ) );
+ if( !p_item ) continue;
+
+ playlist_NodeAddCopy( THEPL, p_item,
+ THEPL->p_playing,
+ PLAYLIST_END );
+ }
+ playlist_Unlock( THEPL );
+}
+
void PLModel::popupInfo()
{
PL_LOCK;
QStringList mrls = selectedURIs();
if( !mrls.isEmpty() )
THEDP->streamingDialog( NULL, mrls[0], false );
-
}
void PLModel::popupSave()
void PLModel::popupExplore()
{
+ char *uri = NULL, *path = NULL;
+
PL_LOCK;
- playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
- i_popup_item );
+ playlist_item_t *p_item = playlist_ItemGetById( p_playlist, i_popup_item );
if( p_item )
{
- input_item_t *p_input = p_item->p_input;
- char *psz_meta = input_item_GetURI( p_input );
- PL_UNLOCK;
- if( psz_meta )
- {
- const char *psz_access;
- const char *psz_demux;
- char *psz_path;
- input_SplitMRL( &psz_access, &psz_demux, &psz_path, psz_meta );
-
- if( !EMPTY_STR( psz_access ) && (
- !strncasecmp( psz_access, "file", 4 ) ||
- !strncasecmp( psz_access, "dire", 4 ) ))
- {
- QFileInfo info( qfu( psz_path ) );
- QDesktopServices::openUrl(
- QUrl::fromLocalFile( info.absolutePath() ) );
- }
- free( psz_meta );
- }
+ input_item_t *p_input = p_item->p_input;
+ uri = input_item_GetURI( p_input );
}
- else
- PL_UNLOCK;
+ PL_UNLOCK;
+
+ if( uri != NULL )
+ {
+ path = make_path( uri );
+ free( uri );
+ }
+ if( path == NULL )
+ return;
+
+ QFileInfo info( qfu( path ) );
+ free( path );
+
+ QDesktopServices::openUrl( QUrl::fromLocalFile( info.absolutePath() ) );
}
void PLModel::popupAddNode()
qtr( I_NEW_DIR ), qtr( I_NEW_DIR_NAME ),
QLineEdit::Normal, QString(), &ok);
if( !ok || name.isEmpty() ) return;
+
PL_LOCK;
playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
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;
}
column > 0 ? column - 1 : -column - 1,
column > 0 ? Qt::AscendingOrder : Qt::DescendingOrder );
}
+
+/* */
+void PLModel::increaseZoom()
+{
+ i_zoom++;
+ emit layoutChanged();
+}
+
+void PLModel::decreaseZoom()
+{
+ i_zoom--;
+ emit layoutChanged();
+}
+
+/******************* Drag and Drop helper class ******************/
+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;
+}