X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fqt4%2Fcomponents%2Fplaylist%2Fstandardpanel.cpp;h=4d073a439e866bf1c2a3104df37552528ea281bd;hb=790811343ae90c501aabd1a40ec375659fd415f2;hp=6bea1c92d463ddce4de2d39cd19d51119b5430d5;hpb=494ace96d068ee8e4b6b689da0ae469c0c0e4fe3;p=vlc diff --git a/modules/gui/qt4/components/playlist/standardpanel.cpp b/modules/gui/qt4/components/playlist/standardpanel.cpp index 6bea1c92d4..4d073a439e 100644 --- a/modules/gui/qt4/components/playlist/standardpanel.cpp +++ b/modules/gui/qt4/components/playlist/standardpanel.cpp @@ -1,10 +1,11 @@ /***************************************************************************** * standardpanel.cpp : The "standard" playlist panel : just a treeview **************************************************************************** - * Copyright (C) 2000-2005 the VideoLAN team + * Copyright (C) 2000-2009 VideoLAN * $Id$ * * Authors: Clément Stenac + * JB Kempf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,30 +21,32 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ + #ifdef HAVE_CONFIG_H # include "config.h" #endif -#include "qt4.hpp" #include "dialogs_provider.hpp" + #include "components/playlist/playlist_model.hpp" -#include "components/playlist/panels.hpp" +#include "components/playlist/standardpanel.hpp" +#include "components/playlist/icon_view.hpp" #include "util/customwidgets.hpp" +#include "menus.hpp" #include -#include #include -#include -#include #include #include #include -#include #include -#include #include #include +#include +#include +#include +#include #include @@ -53,277 +56,214 @@ StandardPLPanel::StandardPLPanel( PlaylistWidget *_parent, intf_thread_t *_p_intf, playlist_t *p_playlist, playlist_item_t *p_root ): - PLPanel( _parent, _p_intf ) + QWidget( _parent ), p_intf( _p_intf ) { - model = new PLModel( p_playlist, p_intf, p_root, -1, this ); - - QVBoxLayout *layout = new QVBoxLayout(); + layout = new QGridLayout( this ); layout->setSpacing( 0 ); layout->setMargin( 0 ); + setMinimumWidth( 300 ); - /* Create and configure the QTreeView */ - view = new QVLCTreeView( 0 ); - view->setSortingEnabled( true ); - view->sortByColumn( 0 , Qt::AscendingOrder ); - view->setModel( model ); - view->setIconSize( QSize( 20, 20 ) ); - view->setAlternatingRowColors( true ); - view->setAnimated( true ); - view->setSelectionMode( QAbstractItemView::ExtendedSelection ); - view->setDragEnabled( true ); - view->setAcceptDrops( true ); - view->setDropIndicatorShown( true ); - view->setAutoScroll( true ); - - /* Configure the size of the header */ - view->header()->resizeSection( 0, 200 ); - view->header()->resizeSection( 1, 80 ); - view->header()->setSortIndicatorShown( true ); - view->header()->setClickable( true ); - view->header()->setContextMenuPolicy( Qt::CustomContextMenu ); - - /* Connections for the TreeView */ - CONNECT( view, activated( const QModelIndex& ) , - model,activateItem( const QModelIndex& ) ); - CONNECT( view, rightClicked( QModelIndex , QPoint ), - this, doPopup( QModelIndex, QPoint ) ); - CONNECT( model, dataChanged( const QModelIndex&, const QModelIndex& ), - this, handleExpansion( const QModelIndex& ) ); - CONNECT( view->header(), customContextMenuRequested( const QPoint & ), - this, popupSelectColumn( QPoint ) ); + iconView = NULL; + treeView = NULL; + model = new PLModel( p_playlist, p_intf, p_root, this ); currentRootId = -1; - CONNECT( parent, rootChanged( int ), this, setCurrentRootId( int ) ); + 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 );*/ + + locationBar = new LocationBar( model ); + layout->addWidget( locationBar, 0, 0 ); + CONNECT( model, rootChanged(), locationBar, setRootIndex() ); + + /* A Spacer and the search possibilities */ + layout->setColumnStretch( 1, 10 ); - /* Buttons configuration */ - QHBoxLayout *buttons = new QHBoxLayout; + SearchLineEdit *search = new SearchLineEdit( this ); + search->setMaximumWidth( 300 ); + layout->addWidget( search, 0, 4 ); + CONNECT( search, textChanged( const QString& ), + this, search( const QString& ) ); + layout->setColumnStretch( 4, 10 ); /* Add item to the playlist button */ - addButton = new QPushButton; - addButton->setIcon( QIcon( ":/pixmaps/playlist_add.png" ) ); + addButton = new QToolButton; + addButton->setIcon( QIcon( ":/buttons/playlist/playlist_add" ) ); addButton->setMaximumWidth( 30 ); BUTTONACT( addButton, popupAdd() ); - buttons->addWidget( addButton ); + layout->addWidget( addButton, 0, 3 ); - /* Random 2-state button */ - randomButton = new QPushButton( this ); - if( model->hasRandom() ) - { - randomButton->setIcon( QIcon( ":/pixmaps/playlist_shuffle_on.png" )); - randomButton->setToolTip( qtr( I_PL_RANDOM )); - } - else - { - randomButton->setIcon( QIcon( ":/pixmaps/playlist_shuffle_off.png" ) ); - randomButton->setToolTip( qtr( I_PL_NORANDOM )); - } - BUTTONACT( randomButton, toggleRandom() ); - buttons->addWidget( randomButton ); + /* Button to switch views */ + QToolButton *viewButton = new QToolButton( this ); + viewButton->setIcon( style()->standardIcon( QStyle::SP_FileDialogDetailedView ) ); + layout->addWidget( viewButton, 0, 2 ); - /* Repeat 3-state button */ - repeatButton = new QPushButton( this ); - if( model->hasRepeat() ) - { - repeatButton->setIcon( QIcon( ":/pixmaps/playlist_repeat_one.png" ) ); - repeatButton->setToolTip( qtr( I_PL_REPEAT )); - } - else if( model->hasLoop() ) - { - repeatButton->setIcon( QIcon( ":/pixmaps/playlist_repeat_all.png" ) ); - repeatButton->setToolTip( qtr( I_PL_LOOP )); - } - else - { - repeatButton->setIcon( QIcon( ":/pixmaps/playlist_repeat_off.png" ) ); - repeatButton->setToolTip( qtr( I_PL_NOREPEAT )); - } - BUTTONACT( repeatButton, toggleRepeat() ); - buttons->addWidget( repeatButton ); + /* View selection menu */ + viewSelectionMapper = new QSignalMapper( this ); + CONNECT( viewSelectionMapper, mapped( int ), this, showView( int ) ); - /* Goto */ - gotoPlayingButton = new QPushButton( "X" , this ); - gotoPlayingButton->setToolTip( qtr( "Show the current item" )); - BUTTONACT( gotoPlayingButton, gotoPlayingItem() ); - buttons->addWidget( gotoPlayingButton ); + QActionGroup *actionGroup = new QActionGroup( this ); - /* A Spacer and the search possibilities */ - QSpacerItem *spacer = new QSpacerItem( 10, 20 ); - buttons->addItem( spacer ); + treeViewAction = actionGroup->addAction( "Detailed view" ); + treeViewAction->setCheckable( true ); + viewSelectionMapper->setMapping( treeViewAction, TREE_VIEW ); + CONNECT( treeViewAction, triggered(), viewSelectionMapper, map() ); - QLabel *filter = new QLabel( qtr(I_PL_SEARCH) + " " ); - buttons->addWidget( filter ); + iconViewAction = actionGroup->addAction( "Icon view" ); + iconViewAction->setCheckable( true ); + viewSelectionMapper->setMapping( iconViewAction, ICON_VIEW ); + CONNECT( iconViewAction, triggered(), viewSelectionMapper, map() ); - searchLine = new ClickLineEdit( qtr(I_PL_FILTER), 0 ); - searchLine->setMinimumWidth( 80 ); - CONNECT( searchLine, textChanged(QString), this, search(QString)); - buttons->addWidget( searchLine ); filter->setBuddy( searchLine ); + BUTTONACT( viewButton, cycleViews() ); + QMenu *viewMenu = new QMenu( this ); + viewMenu->addActions( actionGroup->actions() ); - QPushButton *clear = new QPushButton; - clear->setText( qfu( "CL") ); - clear->setMaximumWidth( 30 ); - clear->setToolTip( qtr( "Clear" )); - BUTTONACT( clear, clearFilter() ); - buttons->addWidget( clear ); + viewButton->setMenu( viewMenu ); - /* Finish the layout */ - layout->addWidget( view ); - layout->addLayout( buttons ); -// layout->addWidget( bar ); - setLayout( layout ); -} + /* Saved Settings */ + getSettings()->beginGroup("Playlist"); -/* Function to toggle between the Repeat states */ -void StandardPLPanel::toggleRepeat() -{ - if( model->hasRepeat() ) - { - model->setRepeat( false ); model->setLoop( true ); - repeatButton->setIcon( QIcon( ":/pixmaps/playlist_repeat_all.png" ) ); - repeatButton->setToolTip( qtr( I_PL_LOOP )); - } - else if( model->hasLoop() ) - { - model->setRepeat( false ) ; model->setLoop( false ); - repeatButton->setIcon( QIcon( ":/pixmaps/playlist_repeat_off.png" ) ); - repeatButton->setToolTip( qtr( I_PL_NOREPEAT )); - } - else - { - model->setRepeat( true ); - repeatButton->setIcon( QIcon( ":/pixmaps/playlist_repeat_one.png" ) ); - repeatButton->setToolTip( qtr( I_PL_REPEAT )); - } + int i_viewMode = getSettings()->value( "view-mode", TREE_VIEW ).toInt(); + showView( i_viewMode ); + + getSettings()->endGroup(); + + CONNECT( THEMIM, leafBecameParent( input_item_t *), + this, browseInto( input_item_t * ) ); + + CONNECT( model, currentChanged( const QModelIndex& ), + this, handleExpansion( const QModelIndex& ) ); } -/* Function to toggle between the Random states */ -void StandardPLPanel::toggleRandom() +StandardPLPanel::~StandardPLPanel() { - bool prev = model->hasRandom(); - model->setRandom( !prev ); - randomButton->setIcon( prev ? - QIcon( ":/pixmaps/playlist_shuffle_off.png" ) : - QIcon( ":/pixmaps/playlist_shuffle_on.png" ) ); - randomButton->setToolTip( prev ? qtr( I_PL_NORANDOM ) : qtr(I_PL_RANDOM ) ); + getSettings()->beginGroup("Playlist"); + if( treeView ) + getSettings()->setValue( "headerStateV2", treeView->header()->saveState() ); + getSettings()->setValue( "view-mode", ( currentView == iconView ) ? ICON_VIEW : TREE_VIEW ); + getSettings()->endGroup(); } +/* Unused anymore, but might be useful, like in right-click menu */ void StandardPLPanel::gotoPlayingItem() { - view->scrollTo( view->currentIndex() ); + currentView->scrollTo( model->currentIndex() ); } -void StandardPLPanel::handleExpansion( const QModelIndex &index ) +void StandardPLPanel::handleExpansion( const QModelIndex& index ) { - if( model->isCurrent( index ) ) - view->scrollTo( index, QAbstractItemView::EnsureVisible ); -} - -void StandardPLPanel::setCurrentRootId( int _new ) -{ - currentRootId = _new; - if( currentRootId == THEPL->p_local_category->i_id || - currentRootId == THEPL->p_local_onelevel->i_id ) - { - addButton->setEnabled( true ); - addButton->setToolTip( qtr(I_PL_ADDPL) ); - } - else if( ( THEPL->p_ml_category && - currentRootId == THEPL->p_ml_category->i_id ) || - ( THEPL->p_ml_onelevel && - currentRootId == THEPL->p_ml_onelevel->i_id ) ) - { - addButton->setEnabled( true ); - addButton->setToolTip( qtr(I_PL_ADDML) ); - } - else - addButton->setEnabled( false ); + assert( currentView ); + currentView->scrollTo( index ); } /* PopupAdd Menu for the Add Menu */ void StandardPLPanel::popupAdd() { QMenu popup; - if( currentRootId == THEPL->p_local_category->i_id || - currentRootId == THEPL->p_local_onelevel->i_id ) + if( currentRootId == THEPL->p_playing->i_id ) { - popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT(simplePLAppendDialog())); - popup.addAction( qtr(I_PL_ADVADD), THEDP, SLOT(PLAppendDialog()) ); + 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 ) ) + else if( THEPL->p_media_library && + currentRootId == THEPL->p_media_library->i_id ) { - popup.addAction( qtr(I_PL_ADDF), THEDP, SLOT(simpleMLAppendDialog())); - popup.addAction( qtr(I_PL_ADVADD), THEDP, SLOT( MLAppendDialog() ) ); + 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() ) ); } -void StandardPLPanel::popupSelectColumn( QPoint pos ) +void StandardPLPanel::popupPlView( const QPoint &point ) { - ContextUpdateMapper = new QSignalMapper(this); - - QMenu selectColMenu; - -#define ADD_META_ACTION( meta ) { \ - QAction* option = selectColMenu.addAction( qfu( psz_column_title( meta ) ) ); \ - option->setCheckable( true ); \ - option->setChecked( model->shownFlags() & meta ); \ - ContextUpdateMapper->setMapping( option, meta ); \ - CONNECT( option, triggered(), ContextUpdateMapper, map() ); \ + QModelIndex index = currentView->indexAt( point ); + QPoint globalPoint = currentView->viewport()->mapToGlobal( point ); + if( !index.isValid() ){ + QVLCMenu::PopupMenu( p_intf, true ); + } + else + { + QItemSelectionModel *selection = currentView->selectionModel(); + QModelIndexList list = selection->selectedIndexes(); + model->popup( index, globalPoint, list ); + } } - CONNECT( ContextUpdateMapper, mapped( int ), model, viewchanged( int ) ); - - ADD_META_ACTION( COLUMN_NUMBER ); - ADD_META_ACTION( COLUMN_TITLE ); - ADD_META_ACTION( COLUMN_DURATION ); - ADD_META_ACTION( COLUMN_ARTIST ); - ADD_META_ACTION( COLUMN_GENRE ); - ADD_META_ACTION( COLUMN_ALBUM ); - ADD_META_ACTION( COLUMN_TRACK_NUMBER ); - ADD_META_ACTION( COLUMN_DESCRIPTION ); - -#undef ADD_META_ACTION +void StandardPLPanel::popupSelectColumn( QPoint pos ) +{ + QMenu menu; + assert( treeView ); - selectColMenu.exec( QCursor::pos() ); + /* We do not offer the option to hide index 0 column, or + * QTreeView will behave weird */ + int i, j; + for( i = 1 << 1, j = 1; i < COLUMN_END; i <<= 1, j++ ) + { + QAction* option = menu.addAction( + qfu( psz_column_title( i ) ) ); + option->setCheckable( true ); + option->setChecked( !treeView->isColumnHidden( j ) ); + selectColumnsSigMapper->setMapping( option, j ); + CONNECT( option, triggered(), selectColumnsSigMapper, map() ); + } + menu.exec( QCursor::pos() ); } -/* ClearFilter LineEdit */ -void StandardPLPanel::clearFilter() +void StandardPLPanel::toggleColumnShown( int i ) { - searchLine->setText( "" ); + treeView->setColumnHidden( i, !treeView->isColumnHidden( i ) ); } /* Search in the playlist */ -void StandardPLPanel::search( QString searchText ) +void StandardPLPanel::search( const QString& searchText ) { model->search( searchText ); } -void StandardPLPanel::doPopup( QModelIndex index, QPoint point ) -{ - if( !index.isValid() ) return; - QItemSelectionModel *selection = view->selectionModel(); - QModelIndexList list = selection->selectedIndexes(); - model->popup( index, point, list ); -} - /* Set the root of the new Playlist */ /* This activated by the selector selection */ -void StandardPLPanel::setRoot( int i_root_id ) +void StandardPLPanel::setRoot( playlist_item_t *p_item ) { QPL_LOCK; - playlist_item_t *p_item = playlist_ItemGetById( THEPL, i_root_id, - pl_Locked ); - assert( p_item ); - p_item = playlist_GetPreferredNode( THEPL, p_item ); assert( p_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_playing ) + { + addButton->setEnabled( true ); + addButton->setToolTip( qtr(I_PL_ADDPL) ); + } + else if( THEPL->p_media_library && p_item == THEPL->p_media_library ) + { + addButton->setEnabled( true ); + addButton->setToolTip( qtr(I_PL_ADDML) ); + } + else + addButton->setEnabled( false ); } void StandardPLPanel::removeItem( int i_id ) @@ -346,10 +286,278 @@ void StandardPLPanel::keyPressEvent( QKeyEvent *e ) void StandardPLPanel::deleteSelection() { - QItemSelectionModel *selection = view->selectionModel(); + QItemSelectionModel *selection = currentView->selectionModel(); QModelIndexList list = selection->selectedIndexes(); model->doDelete( list ); } -StandardPLPanel::~StandardPLPanel() -{} +void StandardPLPanel::createIconView() +{ + iconView = new PlIconView( model, this ); + iconView->setContextMenuPolicy( Qt::CustomContextMenu ); + CONNECT( iconView, customContextMenuRequested( const QPoint & ), + this, popupPlView( const QPoint & ) ); + CONNECT( iconView, activated( const QModelIndex & ), + this, activate( const QModelIndex & ) ); + CONNECT( locationBar, invoked( const QModelIndex & ), + iconView, setRootIndex( const QModelIndex & ) ); + + layout->addWidget( iconView, 1, 0, 1, -1 ); +} + +void StandardPLPanel::createTreeView() +{ + /* Create and configure the QTreeView */ + treeView = new QTreeView; + + treeView->setIconSize( QSize( 20, 20 ) ); + treeView->setAlternatingRowColors( true ); + treeView->setAnimated( true ); + treeView->setUniformRowHeights( true ); + treeView->setSortingEnabled( true ); + treeView->header()->setSortIndicator( -1 , Qt::AscendingOrder ); + treeView->header()->setSortIndicatorShown( true ); + treeView->header()->setClickable( true ); + treeView->header()->setContextMenuPolicy( Qt::CustomContextMenu ); + + treeView->setSelectionBehavior( QAbstractItemView::SelectRows ); + treeView->setSelectionMode( QAbstractItemView::ExtendedSelection ); + treeView->setDragEnabled( true ); + treeView->setAcceptDrops( true ); + treeView->setDropIndicatorShown( true ); + treeView->setContextMenuPolicy( Qt::CustomContextMenu ); + + /* setModel after setSortingEnabled(true), or the model will sort immediately! */ + treeView->setModel( model ); + + if( getSettings()->contains( "headerStateV2" ) ) + { + treeView->header()->restoreState( + getSettings()->value( "headerStateV2" ).toByteArray() ); + } + else + { + for( int m = 1, c = 0; m != COLUMN_END; m <<= 1, c++ ) + { + treeView->setColumnHidden( c, !( m & COLUMN_DEFAULT ) ); + if( m == COLUMN_TITLE ) treeView->header()->resizeSection( c, 200 ); + else if( m == COLUMN_DURATION ) treeView->header()->resizeSection( c, 80 ); + } + } + + /* Connections for the TreeView */ + CONNECT( treeView, activated( const QModelIndex& ), + this, activate( const QModelIndex& ) ); + CONNECT( treeView->header(), customContextMenuRequested( const QPoint & ), + this, popupSelectColumn( QPoint ) ); + CONNECT( treeView, customContextMenuRequested( const QPoint & ), + this, popupPlView( const QPoint & ) ); + + /* SignalMapper for columns */ + selectColumnsSigMapper = new QSignalMapper( this ); + CONNECT( selectColumnsSigMapper, mapped( int ), + this, toggleColumnShown( int ) ); + + /* Finish the layout */ + layout->addWidget( treeView, 1, 0, 1, -1 ); +} + +void StandardPLPanel::showView( int i_view ) +{ + switch( i_view ) + { + case TREE_VIEW: + { + if( treeView == NULL ) + createTreeView(); + locationBar->setIndex( treeView->rootIndex() ); + if( iconView ) iconView->hide(); + treeView->show(); + currentView = treeView; + treeViewAction->setChecked( true ); + break; + } + case ICON_VIEW: + { + if( iconView == NULL ) + createIconView(); + + locationBar->setIndex( iconView->rootIndex() ); + if( treeView ) treeView->hide(); + iconView->show(); + currentView = iconView; + iconViewAction->setChecked( true ); + break; + } + default:; + } +} + +void StandardPLPanel::cycleViews() +{ + if( currentView == iconView ) + showView( TREE_VIEW ); + else if( currentView == treeView ) + 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 ); + } + } + 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; + playlist_Unlock( THEPL ); + model->activateItem( index ); + } +} + +void StandardPLPanel::browseInto( input_item_t *p_input ) +{ + + if( p_input->i_id != last_activated_id ) return; + + playlist_Lock( THEPL ); + + playlist_item_t *p_item = playlist_ItemGetByInput( THEPL, p_input ); + if( !p_item ) + { + playlist_Unlock( THEPL ); + return; + } + + QModelIndex index = model->index( p_item->i_id, 0 ); + + playlist_Unlock( THEPL ); + + if( currentView == iconView ) { + iconView->setRootIndex( index ); + locationBar->setIndex( index ); + } + else + treeView->setExpanded( index, true ); + + last_activated_id = -1; + + +} + +LocationBar::LocationBar( PLModel *m ) +{ + 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 ) +{ + qDeleteAll( buttons ); + buttons.clear(); + QModelIndex i = index; + bool bold = true; + 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() ); + if( bold ) btn->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); + box->insertWidget( 0, btn, bold ? 1 : 0 ); + 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 ); +} + +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.rect = rect(); + //option.features = QStyleOptionButton::Flat; + option.state |= QStyle::State_Enabled; + //option.state |= isChecked() ? QStyle::State_On : QStyle::State_Off; + //if( isDown() ) option.state |= QStyle::State_Sunken; + 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 * -1, 0 ); + p.drawText( rect, Qt::AlignVCenter, + fontMetrics().elidedText( text(), Qt::ElideRight, rect.width() ) ); + + 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() ); + s.setWidth( s.width() + ( 2 * frameWidth ) + ( 2 * PADDING ) + ( b_arrow ? 15 : 0 ) ); + s.setHeight( QPushButton::sizeHint().height() ); + return s; +} + +#undef PADDING