#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>
+#include <QPixmapCache>
#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;
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 ),
{
Qt::ItemFlags flags = QAbstractItemModel::flags( index );
- PLItem *item = index.isValid() ? getItem( index ) : rootItem;
+ const PLItem *item = index.isValid() ? getItem( index ) : rootItem;
if( canEdit() )
{
/* Drop operation */
bool PLModel::dropMimeData( const QMimeData *data, Qt::DropAction action,
- int row, int column, const QModelIndex &parent )
+ int row, int column, const QModelIndex &parent )
{
bool copy = action == Qt::CopyAction;
if( !copy && action != Qt::MoveAction )
PL_LOCK;
playlist_item_t *p_parent =
- playlist_ItemGetByInput( p_playlist, target->p_input );
+ playlist_ItemGetByInput( p_playlist, target->p_input );
if( !p_parent ) return;
if( pos == -1 ) pos = PLAYLIST_END;
if( item->parentItem == target &&
target->children.indexOf( item ) < new_pos )
- model_pos--;
+ model_pos--;
model_items.append( item );
pp_items[i] = p_item;
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 );
}
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 );
}
else if( role == Qt::FontRole )
{
+ QFont f;
+ f.setPointSize( f.pointSize() - 1 );
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( 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 */
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 lst;
for( int i = 0; i < current_selection.size(); 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 );
return root;
- }
+
else if( b_input && root->p_input->i_id == i_id )
- {
- ICACHE( i_id, root );
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;
- }
+ return (*it);
+
else if( b_input && (*it)->p_input->i_id == i_id )
- {
- ICACHE( i_id, (*it) );
- return p_cached_item_bi;
- }
+ return (*it);
+
if( (*it)->children.size() )
{
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 )
+bool PLModel::canEdit() const
{
- int meta = 1;
- int column = 0;
-
- while( column != _column && meta != COLUMN_END )
- {
- meta <<= 1;
- column++;
- }
+ 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 meta;
+QString PLModel::getMeta( const QModelIndex & index, int meta )
+{
+ return index.model()->index( index.row(),
+ columnFromMeta( meta ),
+ index.parent() )
+ .data().toString();
}
-int PLModel::columnFromMeta( int meta_col )
+
+QPixmap PLModel::getArtPixmap( const QModelIndex & index, const QSize & size )
{
- int meta = 1;
- int column = 0;
+ PLItem *item = static_cast<PLItem*>( index.internalPointer() );
+ assert( item );
+
+ if( item == NULL )
+ return NULL;
- while( meta != meta_col && meta != COLUMN_END )
+ QString artUrl = InputManager::decodeArtURL( item->inputItem() );
+
+ /* If empty, take one of the children art URL */
+ if( artUrl.isEmpty() )
{
- meta <<= 1;
- column++;
+ for( int i = 0; i < item->childCount(); i++ )
+ {
+ artUrl = InputManager::decodeArtURL( item->child( i )->inputItem() );
+ if( !artUrl.isEmpty() )
+ break;
+ }
}
- return column;
-}
+ QPixmap artPix;
+ QString key = artUrl + QString("%1%2").arg(size.width()).arg(size.height());
-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
- )
- )
- );
+ /* Lookup in the QPixmapCache */
+ if( !QPixmapCache::find( key, artPix ))
+ {
+ if( artUrl.isEmpty() || !artPix.load( artUrl ) )
+ {
+ key = QString("noart%1%2").arg(size.width()).arg(size.height());
+ if( !QPixmapCache::find( key, artPix ) )
+ {
+ artPix = QPixmap( ":/noart" ).scaled( size,
+ Qt::KeepAspectRatio,
+ Qt::SmoothTransformation );
+ QPixmapCache::insert( key, artPix );
+ }
+ }
+ else
+ {
+ artPix = artPix.scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
+ QPixmapCache::insert( key, artPix );
+ }
+ }
+
+ return artPix;
}
/************************* Updates handling *****************************/
{
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 );
assert( node );
int count = items.size();
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++ )
{
}
/******* 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 );
}
-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 );
endRemoveRows( );
beginInsertRows( idx, 0, searchRoot->children.size() - 1 );
- updateChildren( searchRoot );
+ updateChildren( searchRoot ); // The PL_LOCK is needed here
endInsertRows();
PL_UNLOCK;
return false;
}
+ input_item_t *p_input = p_item->p_input;
+ vlc_gc_incref( p_input );
+
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 ) :
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( !strncasecmp( p_input->psz_uri, "file://", 7 ) )
+ menu.addAction( QIcon( ":/type/folder-grey" ),
+ qtr( I_POP_EXPLORE ), this, SLOT( popupExplore() ) );
menu.addSeparator();
}
if( canEdit() )
}
menu.addMenu( sortingMenu );
}
+ vlc_gc_decref( p_input );
+
if( !menu.isEmpty() )
{
menu.exec( point ); return true;
{
PL_LOCK;
playlist_item_t *p_item = playlist_ItemGetById( p_playlist,
- i_popup_item );
+ 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 ) && (
+ 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( decode_URI( psz_path ) ) );
- QDesktopServices::openUrl(
- QUrl::fromLocalFile( info.absolutePath() ) );
- }
- free( psz_meta );
- }
+ {
+#ifdef WIN32
+ /* Qt openURL doesn't know to open files that starts with a / or \ */
+ if( psz_path[0] == '/' || psz_path[0] == '\\' )
+ psz_path++;
+#endif
+
+ QFileInfo info( qfu( decode_URI( psz_path ) ) );
+ QDesktopServices::openUrl(
+ QUrl::fromLocalFile( info.absolutePath() ) );
+ }
+ free( psz_meta );
+ }
}
else
PL_UNLOCK;
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, PLAYLIST_END, 0, NULL );
- }
PL_UNLOCK;
}