X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fqt4%2Fcomponents%2Fplaylist%2Fstandardpanel.cpp;h=bf81375978f5676fefe9c9d848ee7560f14433df;hb=05d736eac9cb11e55fca0552ff4150cb48004ed8;hp=d2deb7a386d3dcfa571c17ac86b7e36d6d2e1df3;hpb=3834b98eedc37503d888a8bffa03eb48536b1e1f;p=vlc diff --git a/modules/gui/qt4/components/playlist/standardpanel.cpp b/modules/gui/qt4/components/playlist/standardpanel.cpp index d2deb7a386..bf81375978 100644 --- a/modules/gui/qt4/components/playlist/standardpanel.cpp +++ b/modules/gui/qt4/components/playlist/standardpanel.cpp @@ -32,6 +32,7 @@ #include "components/playlist/standardpanel.hpp" #include "components/playlist/icon_view.hpp" #include "util/customwidgets.hpp" +#include "menus.hpp" #include @@ -45,11 +46,16 @@ #include #include #include +#include #include #include "sorting.h" +static const QString viewNames[] = { qtr( "Detailed View" ), + qtr( "Icon View" ), + qtr( "List View" ) }; + StandardPLPanel::StandardPLPanel( PlaylistWidget *_parent, intf_thread_t *_p_intf, playlist_t *p_playlist, @@ -62,59 +68,46 @@ StandardPLPanel::StandardPLPanel( PlaylistWidget *_parent, iconView = NULL; treeView = NULL; + listView = NULL; model = new PLModel( p_playlist, p_intf, p_root, this ); currentRootId = -1; - last_activated_id = -1; - - /* Title label */ - /*title = new QLabel; - QFont titleFont; - titleFont.setPointSize( titleFont.pointSize() + 6 ); - titleFont.setFamily( "Verdana" ); - title->setFont( titleFont ); - layout->addWidget( title, 0, 0 );*/ + currentRootIndexId = -1; + lastActivatedId = -1; locationBar = new LocationBar( model ); + locationBar->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred ); layout->addWidget( locationBar, 0, 0 ); + layout->setColumnStretch( 0, 5 ); + CONNECT( locationBar, invoked( const QModelIndex & ), + this, browseInto( const QModelIndex & ) ); - /* A Spacer and the search possibilities */ - layout->setColumnStretch( 1, 10 ); - - SearchLineEdit *search = new SearchLineEdit( this ); - search->setMaximumWidth( 300 ); - layout->addWidget( search, 0, 4 ); - CONNECT( search, textChanged( const QString& ), + searchEdit = new SearchLineEdit( this ); + searchEdit->setMaximumWidth( 250 ); + searchEdit->setMinimumWidth( 80 ); + layout->addWidget( searchEdit, 0, 2 ); + CONNECT( searchEdit, textChanged( const QString& ), this, search( const QString& ) ); - layout->setColumnStretch( 4, 2 ); - - /* Add item to the playlist button */ - addButton = new QPushButton; - addButton->setIcon( QIcon( ":/buttons/playlist/playlist_add" ) ); - addButton->setMaximumWidth( 30 ); - BUTTONACT( addButton, popupAdd() ); - layout->addWidget( addButton, 0, 3 ); + layout->setColumnStretch( 2, 3 ); /* Button to switch views */ QToolButton *viewButton = new QToolButton( this ); - viewButton->setIcon( style()->standardIcon( QStyle::SP_FileDialogContentsView ) ); - layout->addWidget( viewButton, 0, 2 ); + viewButton->setIcon( style()->standardIcon( QStyle::SP_FileDialogDetailedView ) ); + layout->addWidget( viewButton, 0, 1 ); /* View selection menu */ - viewSelectionMapper = new QSignalMapper; + viewSelectionMapper = new QSignalMapper( this ); CONNECT( viewSelectionMapper, mapped( int ), this, showView( int ) ); QActionGroup *actionGroup = new QActionGroup( this ); - treeViewAction = actionGroup->addAction( "Detailed view" ); - treeViewAction->setCheckable( true ); - viewSelectionMapper->setMapping( treeViewAction, TREE_VIEW ); - CONNECT( treeViewAction, triggered(), viewSelectionMapper, map() ); - - iconViewAction = actionGroup->addAction( "Icon view" ); - iconViewAction->setCheckable( true ); - viewSelectionMapper->setMapping( iconViewAction, ICON_VIEW ); - CONNECT( iconViewAction, triggered(), viewSelectionMapper, map() ); + for( int i = 0; i < VIEW_COUNT; i++ ) + { + viewActions[i] = actionGroup->addAction( viewNames[i] ); + viewActions[i]->setCheckable( true ); + viewSelectionMapper->setMapping( viewActions[i], i ); + CONNECT( viewActions[i], triggered(), viewSelectionMapper, map() ); + } BUTTONACT( viewButton, cycleViews() ); QMenu *viewMenu = new QMenu( this ); @@ -135,6 +128,7 @@ StandardPLPanel::StandardPLPanel( PlaylistWidget *_parent, CONNECT( model, currentChanged( const QModelIndex& ), this, handleExpansion( const QModelIndex& ) ); + CONNECT( model, rootChanged(), this, handleRootChange() ); } StandardPLPanel::~StandardPLPanel() @@ -142,7 +136,12 @@ StandardPLPanel::~StandardPLPanel() getSettings()->beginGroup("Playlist"); if( treeView ) getSettings()->setValue( "headerStateV2", treeView->header()->saveState() ); - getSettings()->setValue( "view-mode", ( currentView == iconView ) ? ICON_VIEW : TREE_VIEW ); + if( currentView == treeView ) + getSettings()->setValue( "view-mode", TREE_VIEW ); + else if( currentView == listView ) + getSettings()->setValue( "view-mode", LIST_VIEW ); + else if( currentView == iconView ) + getSettings()->setValue( "view-mode", ICON_VIEW ); getSettings()->endGroup(); } @@ -158,29 +157,9 @@ void StandardPLPanel::handleExpansion( const QModelIndex& index ) currentView->scrollTo( index ); } -/* PopupAdd Menu for the Add Menu */ -void StandardPLPanel::popupAdd() +void StandardPLPanel::handleRootChange() { - QMenu popup; - if( currentRootId == THEPL->p_local_category->i_id || - currentRootId == THEPL->p_local_onelevel->i_id ) - { - popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT( simplePLAppendDialog()) ); - popup.addAction( qtr(I_PL_ADDDIR), THEDP, SLOT( PLAppendDir()) ); - popup.addAction( qtr(I_OP_ADVOP), THEDP, SLOT( PLAppendDialog()) ); - } - else if( ( THEPL->p_ml_category && - currentRootId == THEPL->p_ml_category->i_id ) || - ( THEPL->p_ml_onelevel && - currentRootId == THEPL->p_ml_onelevel->i_id ) ) - { - popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT( simpleMLAppendDialog()) ); - popup.addAction( qtr(I_PL_ADDDIR), THEDP, SLOT( MLAppendDir() ) ); - popup.addAction( qtr(I_OP_ADVOP), THEDP, SLOT( MLAppendDialog() ) ); - } - - popup.exec( QCursor::pos() - addButton->mapFromGlobal( QCursor::pos() ) - + QPoint( 0, addButton->height() ) ); + browseInto(); } void StandardPLPanel::popupPlView( const QPoint &point ) @@ -189,7 +168,9 @@ void StandardPLPanel::popupPlView( const QPoint &point ) QPoint globalPoint = currentView->viewport()->mapToGlobal( point ); QItemSelectionModel *selection = currentView->selectionModel(); QModelIndexList list = selection->selectedIndexes(); - model->popup( index, globalPoint, list ); + + if( !model->popup( index, globalPoint, list ) ) + QVLCMenu::PopupMenu( p_intf, true ); } void StandardPLPanel::popupSelectColumn( QPoint pos ) @@ -220,67 +201,58 @@ void StandardPLPanel::toggleColumnShown( int i ) /* Search in the playlist */ void StandardPLPanel::search( const QString& searchText ) { - model->search( searchText ); + bool flat = currentView == iconView || currentView == listView; + model->search( searchText, + flat ? currentView->rootIndex() : QModelIndex(), + !flat ); } /* Set the root of the new Playlist */ /* This activated by the selector selection */ void StandardPLPanel::setRoot( playlist_item_t *p_item ) { - QPL_LOCK; - assert( p_item ); - - playlist_item_t *p_pref_item = playlist_GetPreferredNode( THEPL, p_item ); - if( p_pref_item ) p_item = p_pref_item; - - /* needed for popupAdd() */ - currentRootId = p_item->i_id; - - /* cosmetics, ..still need playlist locking.. */ - /*char *psz_title = input_item_GetName( p_item->p_input ); - title->setText( qfu(psz_title) ); - free( psz_title );*/ - - QPL_UNLOCK; - - /* do THE job */ model->rebuild( p_item ); +} - locationBar->setIndex( QModelIndex() ); - - /* enable/disable adding */ - if( p_item == THEPL->p_local_category || - p_item == THEPL->p_local_onelevel ) - { - addButton->setEnabled( true ); - addButton->setToolTip( qtr(I_PL_ADDPL) ); - } - else if( ( THEPL->p_ml_category && p_item == THEPL->p_ml_category) || - ( THEPL->p_ml_onelevel && p_item == THEPL->p_ml_onelevel ) ) +void StandardPLPanel::browseInto( const QModelIndex &index ) +{ + if( currentView == iconView || currentView == listView ) { - addButton->setEnabled( true ); - addButton->setToolTip( qtr(I_PL_ADDML) ); + currentRootIndexId = model->itemId( index );; + currentView->setRootIndex( index ); } - else - addButton->setEnabled( false ); + + locationBar->setIndex( index ); + model->search( QString(), index, false ); + searchEdit->clear(); +} + +void StandardPLPanel::browseInto( ) +{ + browseInto( currentRootIndexId != -1 && currentView != treeView ? + model->index( currentRootIndexId, 0 ) : + QModelIndex() ); } -void StandardPLPanel::removeItem( int i_id ) +void StandardPLPanel::wheelEvent( QWheelEvent *e ) { - model->removeItem( i_id ); + // Accept this event in order to prevent unwanted volume up/down changes + e->accept(); } -/* Delete and Suppr key remove the selection - FilterKey function and code function */ -void StandardPLPanel::keyPressEvent( QKeyEvent *e ) +bool StandardPLPanel::eventFilter ( QObject * watched, QEvent * event ) { - switch( e->key() ) + if (event->type() == QEvent::KeyPress) { - case Qt::Key_Back: - case Qt::Key_Delete: - deleteSelection(); - break; + QKeyEvent *keyEvent = static_cast(event); + if( keyEvent->key() == Qt::Key_Delete || + keyEvent->key() == Qt::Key_Backspace ) + { + deleteSelection(); + return true; + } } + return false; } void StandardPLPanel::deleteSelection() @@ -298,12 +270,23 @@ void StandardPLPanel::createIconView() this, popupPlView( const QPoint & ) ); CONNECT( iconView, activated( const QModelIndex & ), this, activate( const QModelIndex & ) ); - CONNECT( locationBar, invoked( const QModelIndex & ), - iconView, setRootIndex( const QModelIndex & ) ); - + iconView->installEventFilter( this ); layout->addWidget( iconView, 1, 0, 1, -1 ); } +void StandardPLPanel::createListView() +{ + listView = new PlListView( model, this ); + listView->setContextMenuPolicy( Qt::CustomContextMenu ); + CONNECT( listView, customContextMenuRequested( const QPoint & ), + this, popupPlView( const QPoint & ) ); + CONNECT( listView, activated( const QModelIndex & ), + this, activate( const QModelIndex & ) ); + listView->installEventFilter( this ); + layout->addWidget( listView, 1, 0, 1, -1 ); +} + + void StandardPLPanel::createTreeView() { /* Create and configure the QTreeView */ @@ -351,6 +334,7 @@ void StandardPLPanel::createTreeView() this, popupSelectColumn( QPoint ) ); CONNECT( treeView, customContextMenuRequested( const QPoint & ), this, popupPlView( const QPoint & ) ); + treeView->installEventFilter( this ); /* SignalMapper for columns */ selectColumnsSigMapper = new QSignalMapper( this ); @@ -369,11 +353,11 @@ void StandardPLPanel::showView( int i_view ) { if( treeView == NULL ) createTreeView(); - locationBar->setIndex( treeView->rootIndex() ); if( iconView ) iconView->hide(); + if( listView ) listView->hide(); treeView->show(); currentView = treeView; - treeViewAction->setChecked( true ); + viewActions[i_view]->setChecked( true ); break; } case ICON_VIEW: @@ -381,15 +365,30 @@ void StandardPLPanel::showView( int i_view ) if( iconView == NULL ) createIconView(); - locationBar->setIndex( iconView->rootIndex() ); if( treeView ) treeView->hide(); + if( listView ) listView->hide(); iconView->show(); currentView = iconView; - iconViewAction->setChecked( true ); + viewActions[i_view]->setChecked( true ); break; } - default:; + case LIST_VIEW: + { + if( listView == NULL ) + createListView(); + + if( treeView ) treeView->hide(); + if( iconView ) iconView->hide(); + listView->show(); + currentView = listView; + viewActions[i_view]->setChecked( true ); + break; } + default: return; + } + + browseInto(); + gotoPlayingItem(); } void StandardPLPanel::cycleViews() @@ -397,33 +396,26 @@ void StandardPLPanel::cycleViews() if( currentView == iconView ) showView( TREE_VIEW ); else if( currentView == treeView ) + showView( LIST_VIEW ); + else if( currentView == listView ) showView( ICON_VIEW ); else assert( 0 ); } -void StandardPLPanel::wheelEvent( QWheelEvent *e ) -{ - // Accept this event in order to prevent unwanted volume up/down changes - e->accept(); -} - void StandardPLPanel::activate( const QModelIndex &index ) { if( model->hasChildren( index ) ) { - if( currentView == iconView ) { - iconView->setRootIndex( index ); - //title->setText( index.data().toString() ); - locationBar->setIndex( index ); - } + if( currentView != treeView ) + browseInto( index ); } else { playlist_Lock( THEPL ); playlist_item_t *p_item = playlist_ItemGetById( THEPL, model->itemId( index ) ); p_item->i_flags |= PLAYLIST_SUBITEM_STOP_FLAG; - last_activated_id = p_item->p_input->i_id;//model->getItem( index )->inputItem()->i_id; + lastActivatedId = p_item->p_input->i_id; playlist_Unlock( THEPL ); model->activateItem( index ); } @@ -432,67 +424,132 @@ void StandardPLPanel::activate( const QModelIndex &index ) void StandardPLPanel::browseInto( input_item_t *p_input ) { - if( p_input->i_id != last_activated_id ) return; + if( p_input->i_id != lastActivatedId ) return; playlist_Lock( THEPL ); playlist_item_t *p_item = playlist_ItemGetByInput( THEPL, p_input ); - assert( p_item != NULL ); + if( !p_item ) + { + playlist_Unlock( THEPL ); + return; + } QModelIndex index = model->index( p_item->i_id, 0 ); - if( currentView == iconView ) { - iconView->setRootIndex( index ); - locationBar->setIndex( index ); - } - else + + playlist_Unlock( THEPL ); + + if( currentView == treeView ) treeView->setExpanded( index, true ); + else + browseInto( index ); + + lastActivatedId = -1; - last_activated_id = -1; - playlist_Unlock( THEPL ); } LocationBar::LocationBar( PLModel *m ) { - model = m; - mapper = new QSignalMapper( this ); - CONNECT( mapper, mapped( int ), this, invoke( int ) ); + model = m; + mapper = new QSignalMapper( this ); + CONNECT( mapper, mapped( int ), this, invoke( int ) ); + + box = new QHBoxLayout; + box->setSpacing( 0 ); + box->setContentsMargins( 0, 0, 0, 0 ); + setLayout( box ); } void LocationBar::setIndex( const QModelIndex &index ) { - clear(); - QAction *prev = NULL; - QModelIndex i = index; - QFont font; - QFontMetrics metrics( font ); - font.setBold( true ); - while( true ) - { - PLItem *item = model->getItem( i ); - - QToolButton *btn = new QToolButton; - char *fb_name = input_item_GetTitleFbName( item->inputItem() ); - QString text = qfu(fb_name); - free(fb_name); - text = QString("/ ") + metrics.elidedText( text, Qt::ElideRight, 150 ); - btn->setText( text ); - btn->setFont( font ); - prev = insertWidget( prev, btn ); - - mapper->setMapping( btn, item->id() ); - CONNECT( btn, clicked( ), mapper, map( ) ); - - font = QFont(); - - if( i.isValid() ) i = i.parent(); - else break; - } + qDeleteAll( buttons ); + buttons.clear(); + QModelIndex i = index; + bool bold = true; + box->addStretch(); + while( true ) + { + PLItem *item = model->getItem( i ); + + char *fb_name = input_item_GetTitleFbName( item->inputItem() ); + QString text = qfu(fb_name); + free(fb_name); + QAbstractButton *btn = new LocationButton( text, bold, i.isValid() ); + btn->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Fixed ); + box->insertWidget( 0, btn ); + buttons.append( btn ); + + mapper->setMapping( btn, item->id() ); + CONNECT( btn, clicked( ), mapper, map( ) ); + + bold = false; + + if( i.isValid() ) i = i.parent(); + else break; + } +} + +void LocationBar::setRootIndex() +{ + setIndex( QModelIndex() ); } void LocationBar::invoke( int i_id ) { - QModelIndex index = model->index( i_id, 0 ); - setIndex( index ); - emit invoked ( index ); + QModelIndex index = model->index( i_id, 0 ); + emit invoked ( index ); +} + +LocationButton::LocationButton( const QString &text, bool bold, bool arrow ) + : b_arrow( arrow ) +{ + QFont font; + font.setBold( bold ); + setFont( font ); + setText( text ); } + +#define PADDING 4 + +void LocationButton::paintEvent ( QPaintEvent * event ) +{ + QStyleOptionButton option; + option.initFrom( this ); + option.state |= QStyle::State_Enabled; + QPainter p( this ); + + if( underMouse() ) + style()->drawControl( QStyle::CE_PushButtonBevel, &option, &p ); + + int margin = style()->pixelMetric(QStyle::PM_DefaultFrameWidth,0,this) + PADDING; + + QRect rect = option.rect.adjusted( b_arrow ? 15 + margin : margin, 0, -margin, 0 ); + + QString str( text() ); + /* This check is absurd, but either it is not done properly inside elidedText(), + or boundingRect() is wrong */ + if( rect.width() < fontMetrics().boundingRect( text() ).width() ) + str = fontMetrics().elidedText( text(), Qt::ElideRight, rect.width() ); + p.drawText( rect, Qt::AlignVCenter | Qt::AlignLeft, str ); + + if( b_arrow ) + { + option.rect.setX( margin ); + option.rect.setWidth( 8 ); + style()->drawPrimitive( QStyle::PE_IndicatorArrowRight, &option, &p ); + } +} + +QSize LocationButton::sizeHint() const +{ + int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth,0,this); + QSize s( fontMetrics().boundingRect( text() ).size() ); + /* Add two pixels to width: font metrics are buggy, if you pass text through elidation + with exactly the width of its bounding rect, sometimes it still elides */ + s.setWidth( s.width() + ( 2 * frameWidth ) + ( 2 * PADDING ) + ( b_arrow ? 15 : 0 ) + 2 ); + s.setHeight( QPushButton::sizeHint().height() ); + return s; +} + +#undef PADDING