X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fqt4%2Fcomponents%2Fplaylist%2Fplaylist_model.cpp;h=7f7fe312e568173163a45147ffbdbcf7aa2e6652;hb=00d1ebdf0d888f9b83197e58cc2bee444fb7dd59;hp=38688672ae30639009c8e9dde4c21fe0cd6da45c;hpb=eb2da50b47b1af2d9b38a982579f34873d1bb081;p=vlc diff --git a/modules/gui/qt4/components/playlist/playlist_model.cpp b/modules/gui/qt4/components/playlist/playlist_model.cpp index 38688672ae..7f7fe312e5 100644 --- a/modules/gui/qt4/components/playlist/playlist_model.cpp +++ b/modules/gui/qt4/components/playlist/playlist_model.cpp @@ -28,26 +28,27 @@ #endif #include "qt4.hpp" -#include "dialogs_provider.hpp" #include "components/playlist/playlist_model.hpp" -#include "dialogs/mediainfo.hpp" -#include "dialogs/playlist.hpp" -#include +#include "dialogs_provider.hpp" /* THEDP */ +#include "input_manager.hpp" /* THEMIM */ +#include "dialogs/mediainfo.hpp" /* MediaInfo Dialog */ +#include "dialogs/playlist.hpp" /* Playlist Dialog */ + +#include /* I_DIR */ #include "pixmaps/types/type_unknown.xpm" +#include "sorting.h" #include #include #include #include -#include -#include #include #include #include #include - -#include "sorting.h" +#include +#include #define I_NEW_DIR \ I_DIR_OR_FOLDER( N_("Create Directory"), N_( "Create Folder" ) ) @@ -65,9 +66,8 @@ PLModel::PLModel( playlist_t *_p_playlist, /* THEPL */ 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; @@ -91,9 +91,9 @@ PLModel::PLModel( playlist_t *_p_playlist, /* THEPL */ 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 ), @@ -115,7 +115,7 @@ 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() ) { @@ -187,7 +187,7 @@ QMimeData *PLModel::mimeData( const QModelIndexList &indexes ) const /* 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 ) @@ -209,7 +209,7 @@ void PLModel::dropAppendCopy( const PlMimeData *plMimeData, PLItem *target, int 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; @@ -269,7 +269,7 @@ void PLModel::dropMove( const PlMimeData * plMimeData, PLItem *target, int row ) if( item->parentItem == target && target->children.indexOf( item ) < new_pos ) - model_pos--; + model_pos--; model_items.append( item ); pp_items[i] = p_item; @@ -301,7 +301,7 @@ void PLModel::removeItem( int i_id ) 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 ); @@ -321,14 +321,14 @@ void PLModel::activateItem( playlist_item_t *p_item ) } 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() ); @@ -337,6 +337,21 @@ QVariant PLModel::data( const QModelIndex &index, int role ) const 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 ); @@ -352,10 +367,11 @@ QVariant PLModel::data( const QModelIndex &index, int role ) const } 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 ) ) { @@ -420,7 +436,7 @@ 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; @@ -432,9 +448,9 @@ QModelIndex PLModel::index( int row, int column, const QModelIndex &parent ) 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 */ @@ -485,7 +501,7 @@ int PLModel::columnCount( const QModelIndex &i) const 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(); } @@ -494,7 +510,7 @@ QStringList PLModel::selectedURIs() 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; @@ -514,115 +530,115 @@ QStringList PLModel::selectedURIs() 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::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( 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 *****************************/ @@ -656,15 +672,17 @@ void PLModel::processItemAppend( int i_item, int i_parent ) { 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 ) @@ -675,18 +693,18 @@ void PLModel::processItemAppend( int i_item, int i_parent ) 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 ); @@ -735,6 +753,7 @@ void PLModel::insertChildren( PLItem *node, QList& items, int i_pos ) 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++ ) { @@ -835,12 +854,12 @@ void PLModel::recurseDelete( QList children, QModelIndexList *fullList } /******* 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 ); @@ -911,7 +930,7 @@ void PLModel::search( const QString& search_text, const QModelIndex & idx, bool endRemoveRows( ); beginInsertRows( idx, 0, searchRoot->children.size() - 1 ); - updateChildren( searchRoot ); + updateChildren( searchRoot ); // The PL_LOCK is needed here endInsertRows(); PL_UNLOCK; @@ -935,6 +954,9 @@ bool PLModel::popup( const QModelIndex & index, const QPoint &point, const QMode 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 ) : @@ -956,8 +978,9 @@ bool PLModel::popup( const QModelIndex & index, const QPoint &point, const QMode 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() ) @@ -1004,6 +1027,8 @@ bool PLModel::popup( const QModelIndex & index, const QPoint &point, const QMode } menu.addMenu( sortingMenu ); } + vlc_gc_decref( p_input ); + if( !menu.isEmpty() ) { menu.exec( point ); return true; @@ -1065,29 +1090,35 @@ void PLModel::popupExplore() { 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; @@ -1100,13 +1131,12 @@ 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, PLAYLIST_END, 0, NULL ); - } PL_UNLOCK; }