X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fqt4%2Fcomponents%2Fplaylist%2Fselector.cpp;h=6463176aeb16ba9044665f7450d10d6d174b4862;hb=62c5847095178cf70de977c3c339d5293668979b;hp=114cc3748a6098fd0f4ff2cfd3b167c8e6179a62;hpb=f33816a822905117534229be1d41b1b2bd98a59e;p=vlc diff --git a/modules/gui/qt4/components/playlist/selector.cpp b/modules/gui/qt4/components/playlist/selector.cpp index 114cc3748a..6463176aeb 100644 --- a/modules/gui/qt4/components/playlist/selector.cpp +++ b/modules/gui/qt4/components/playlist/selector.cpp @@ -31,6 +31,7 @@ #include "playlist_model.hpp" /* plMimeData */ #include "input_manager.hpp" /* MainInputManager, for podcast */ +#include #include #include #include @@ -39,6 +40,9 @@ #include #include #include +#include +#include +#include #include #include @@ -140,6 +144,12 @@ PLSelector::PLSelector( QWidget *p, intf_thread_t *_p_intf ) createItems(); + setRootIsDecorated( false ); + setIndentation( 5 ); + /* Expand at least to show level 2 */ + for ( int i = 0; i < topLevelItemCount(); i++ ) + expandItem( topLevelItem( i ) ); + /*** * We need to react to both clicks and activation (enter-key) here. * We use curItem to avoid rebuilding twice. @@ -181,29 +191,73 @@ PLSelItem * putPLData( PLSelItem* item, playlist_item_t* plItem ) return item; } +/* + * Reads and updates the playlist's duration as [xx:xx] after the label in the tree + * item - the treeview item to get the duration for + * prefix - the string to use before the time (should be the category name) + */ +void PLSelector::updateTotalDuration( PLSelItem* item, const char* prefix ) +{ + /* Getting the playlist */ + QVariant playlistVariant = item->treeItem()->data( 0, PL_ITEM_ROLE ); + playlist_item_t* node = playlistVariant.value(); + + /* Get the duration of the playlist item */ + playlist_Lock( THEPL ); + mtime_t mt_duration = playlist_GetNodeDuration( node ); + playlist_Unlock( THEPL ); + + /* Formatting time */ + QString qs_timeLabel( prefix ); + + int i_seconds = mt_duration / 1000000; + int i_minutes = i_seconds / 60; + i_seconds = i_seconds % 60; + if( i_minutes >= 60 ) + { + int i_hours = i_minutes / 60; + i_minutes = i_minutes % 60; + qs_timeLabel += QString(" [%1:%2:%3]").arg( i_hours ).arg( i_minutes, 2, 10, QChar('0') ).arg( i_seconds, 2, 10, QChar('0') ); + } + else + qs_timeLabel += QString( " [%1:%2]").arg( i_minutes, 2, 10, QChar('0') ).arg( i_seconds, 2, 10, QChar('0') ); + + item->setText( qs_timeLabel ); +} + void PLSelector::createItems() { /* PL */ - PLSelItem *pl = putPLData( addItem( PL_ITEM_TYPE, N_("Playlist"), true ), + playlistItem = putPLData( addItem( PL_ITEM_TYPE, N_("Playlist"), true ), THEPL->p_playing ); - pl->treeItem()->setData( 0, SPECIAL_ROLE, QVariant( IS_PL ) ); - setCurrentItem( pl->treeItem() ); + playlistItem->treeItem()->setData( 0, SPECIAL_ROLE, QVariant( IS_PL ) ); + playlistItem->treeItem()->setData( 0, Qt::DecorationRole, QIcon( ":/sidebar/playlist" ) ); + setCurrentItem( playlistItem->treeItem() ); /* ML */ PLSelItem *ml = putPLData( addItem( PL_ITEM_TYPE, N_("Media Library"), true ), THEPL->p_media_library ); ml->treeItem()->setData( 0, SPECIAL_ROLE, QVariant( IS_ML ) ); + ml->treeItem()->setData( 0, Qt::DecorationRole, QIcon( ":/sidebar/library" ) ); #ifdef MEDIA_LIBRARY /* SQL ML */ - addItem( SQL_ML_TYPE, "SQL Media Library" )->treeItem(); + ml = addItem( SQL_ML_TYPE, "SQL Media Library" )->treeItem(); + ml->treeItem()->setData( 0, Qt::DecorationRole, QIcon( ":/sidebar/library" ) ); #endif /* SD nodes */ - QTreeWidgetItem *mycomp = addItem( CATEGORY_TYPE, N_("My Computer") )->treeItem(); - QTreeWidgetItem *devices = addItem( CATEGORY_TYPE, N_("Devices") )->treeItem(); - QTreeWidgetItem *lan = addItem( CATEGORY_TYPE, N_("Local Network") )->treeItem(); - QTreeWidgetItem *internet = addItem( CATEGORY_TYPE, N_("Internet") )->treeItem(); + QTreeWidgetItem *mycomp = addItem( CATEGORY_TYPE, N_("My Computer"), false, true )->treeItem(); + QTreeWidgetItem *devices = addItem( CATEGORY_TYPE, N_("Devices"), false, true )->treeItem(); + QTreeWidgetItem *lan = addItem( CATEGORY_TYPE, N_("Local Network"), false, true )->treeItem(); + QTreeWidgetItem *internet = addItem( CATEGORY_TYPE, N_("Internet"), false, true )->treeItem(); + +#define NOT_SELECTABLE(w) w->setFlags( w->flags() ^ Qt::ItemIsSelectable ); + NOT_SELECTABLE( mycomp ); + NOT_SELECTABLE( devices ); + NOT_SELECTABLE( lan ); + NOT_SELECTABLE( internet ); +#undef NOT_SELECTABLE /* SD subnodes */ char **ppsz_longnames; @@ -219,34 +273,72 @@ void PLSelector::createItems() //msg_Dbg( p_intf, "Adding a SD item: %s", *ppsz_longname ); PLSelItem *selItem; + QIcon icon; + QString name( *ppsz_name ); switch( *p_category ) { case SD_CAT_INTERNET: { - selItem = addItem( SD_TYPE, *ppsz_longname, false, internet ); - if( !strncmp( *ppsz_name, "podcast", 7 ) ) + selItem = addItem( SD_TYPE, *ppsz_longname, false, false, internet ); + if( name.startsWith( "podcast" ) ) { selItem->treeItem()->setData( 0, SPECIAL_ROLE, QVariant( IS_PODCAST ) ); selItem->addAction( ADD_ACTION, qtr( "Subscribe to a podcast" ) ); CONNECT( selItem, action( PLSelItem* ), this, podcastAdd( PLSelItem* ) ); podcastsParent = selItem->treeItem(); + icon = QIcon( ":/sidebar/podcast" ); + } + else if ( name.startsWith( "lua{" ) ) + { + int i_head = name.indexOf( "sd='" ) + 4; + int i_tail = name.indexOf( '\'', i_head ); + name.mid( i_head, i_tail - i_head ); + QString iconname = QString( ":/sidebar/sd/%1" ).arg( name.mid( i_head, i_tail - i_head ) ); + QResource resource( iconname ); + if ( !resource.isValid() ) + icon = QIcon( ":/sidebar/network" ); + else + icon = QIcon( iconname ); } } break; case SD_CAT_DEVICES: - selItem = addItem( SD_TYPE, *ppsz_longname, false, devices ); + name = name.mid( 0, name.indexOf( '{' ) ); + selItem = addItem( SD_TYPE, *ppsz_longname, false, false, devices ); + if ( name == "xcb_apps" ) + icon = QIcon( ":/sidebar/screen" ); + else if ( name == "mtp" ) + icon = QIcon( ":/sidebar/mtp" ); + else if ( name == "disc" ) + icon = QIcon( ":/sidebar/disc" ); + else + icon = QIcon( ":/sidebar/capture" ); break; case SD_CAT_LAN: - selItem = addItem( SD_TYPE, *ppsz_longname, false, lan ); + selItem = addItem( SD_TYPE, *ppsz_longname, false, false, lan ); + icon = QIcon( ":/sidebar/lan" ); break; case SD_CAT_MYCOMPUTER: - selItem = addItem( SD_TYPE, *ppsz_longname, false, mycomp ); + name = name.mid( 0, name.indexOf( '{' ) ); + selItem = addItem( SD_TYPE, *ppsz_longname, false, false, mycomp ); + if ( name == "video_dir" ) + icon = QIcon( ":/sidebar/movie" ); + else if ( name == "audio_dir" ) + icon = QIcon( ":/sidebar/music" ); + else if ( name == "picture_dir" ) + icon = QIcon( ":/sidebar/pictures" ); + else + icon = QIcon( ":/sidebar/movie" ); break; default: selItem = addItem( SD_TYPE, *ppsz_longname ); } + selItem->treeItem()->setData( 0, SD_CATEGORY_ROLE, *p_category ); putSDData( selItem, *ppsz_name, *ppsz_longname ); + if ( ! icon.isNull() ) + selItem->treeItem()->setData( 0, Qt::DecorationRole, icon ); + free( *ppsz_name ); free( *ppsz_longname ); } @@ -290,6 +382,7 @@ void PLSelector::setSource( QTreeWidgetItem *item ) else if( i_type == SQL_ML_TYPE ) { emit categoryActivated( NULL, true ); + curItem = item; return; } #endif @@ -327,17 +420,24 @@ void PLSelector::setSource( QTreeWidgetItem *item ) /* */ if( pl_item ) + { emit categoryActivated( pl_item, false ); + emit SDCategorySelected( + item->data( 0, SD_CATEGORY_ROLE ).toInt() + & ( SD_CAT_INTERNET | SD_CAT_LAN ) + ); + } } PLSelItem * PLSelector::addItem ( - SelectorItemType type, const char* str, bool drop, + SelectorItemType type, const char* str, bool drop, bool bold, QTreeWidgetItem* parentItem ) { QTreeWidgetItem *item = parentItem ? new QTreeWidgetItem( parentItem ) : new QTreeWidgetItem( this ); PLSelItem *selItem = new PLSelItem( item, qtr( str ) ); + if ( bold ) selItem->setStyleSheet( "font-weight: bold;" ); setItemWidget( item, 0, selItem ); item->setData( 0, TYPE_ROLE, (int)type ); if( !drop ) item->setFlags( item->flags() & ~Qt::ItemIsDropEnabled ); @@ -350,7 +450,7 @@ PLSelItem *PLSelector::addPodcastItem( playlist_item_t *p_item ) vlc_gc_incref( p_item->p_input ); char *psz_name = input_item_GetName( p_item->p_input ); - PLSelItem *item = addItem( PL_ITEM_TYPE, psz_name, false, podcastsParent ); + PLSelItem *item = addItem( PL_ITEM_TYPE, psz_name, false, false, podcastsParent ); free( psz_name ); item->addAction( RM_ACTION, qtr( "Remove this podcast subscription" ) ); @@ -411,7 +511,8 @@ void PLSelector::dragMoveEvent ( QDragMoveEvent * event ) void PLSelector::plItemAdded( int item, int parent ) { - if( parent != podcastsParentId ) return; + updateTotalDuration(playlistItem, "Playlist"); + if( parent != podcastsParentId || podcastsParent == NULL ) return; playlist_Lock( THEPL ); @@ -443,6 +544,9 @@ void PLSelector::plItemAdded( int item, int parent ) void PLSelector::plItemRemoved( int id ) { + updateTotalDuration(playlistItem, "Playlist"); + if( !podcastsParent ) return; + int c = podcastsParent->childCount(); for( int i = 0; i < c; i++ ) { @@ -460,6 +564,11 @@ void PLSelector::plItemRemoved( int id ) void PLSelector::inputItemUpdate( input_item_t *arg ) { + updateTotalDuration(playlistItem, "Playlist"); + + if( podcastsParent == NULL ) + return; + int c = podcastsParent->childCount(); for( int i = 0; i < c; i++ ) { @@ -478,6 +587,8 @@ void PLSelector::inputItemUpdate( input_item_t *arg ) void PLSelector::podcastAdd( PLSelItem * ) { + assert( podcastsParent ); + bool ok; QString url = QInputDialog::getText( this, qtr( "Subscribe" ), qtr( "Enter URL of the podcast to subscribe to:" ), @@ -501,9 +612,9 @@ void PLSelector::podcastRemove( PLSelItem* item ) question = question.arg( item->text() ); QMessageBox::StandardButton res = QMessageBox::question( this, qtr( "Unsubscribe" ), question, - QMessageBox::Ok | QMessageBox::Cancel, - QMessageBox::Cancel ); - if( res == QMessageBox::Cancel ) return; + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No ); + if( res == QMessageBox::No ) return; input_item_t *input = item->treeItem()->data( 0, IN_ITEM_ROLE ).value(); if( !input ) return; @@ -550,6 +661,12 @@ int PLSelector::getCurrentItemCategory() void PLSelector::wheelEvent( QWheelEvent *e ) { + if( verticalScrollBar()->isVisible() && ( + (verticalScrollBar()->value() != verticalScrollBar()->minimum() && e->delta() >= 0 ) || + (verticalScrollBar()->value() != verticalScrollBar()->maximum() && e->delta() < 0 ) + ) ) + QApplication::sendEvent(verticalScrollBar(), e); + // Accept this event in order to prevent unwanted volume up/down changes e->accept(); }