[vlc-devel] commit: Qt: locationBar hides parent locations that don't fit in ( Jakob Leben )
git version control
git at videolan.org
Tue Feb 16 02:33:31 CET 2010
vlc | branch: master | Jakob Leben <jleben at videolan.org> | Tue Feb 16 02:28:46 2010 +0100| [beec07229c941fdc39cea99618383ac9d260f9a5] | committer: Jakob Leben
Qt: locationBar hides parent locations that don't fit in
Instead it shows a "..." button which opens a menu with those locations.
Current location is thus always displayed as wide as possible.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=beec07229c941fdc39cea99618383ac9d260f9a5
---
.../gui/qt4/components/playlist/standardpanel.cpp | 140 ++++++++++++++++----
.../gui/qt4/components/playlist/standardpanel.hpp | 29 +++--
2 files changed, 133 insertions(+), 36 deletions(-)
diff --git a/modules/gui/qt4/components/playlist/standardpanel.cpp b/modules/gui/qt4/components/playlist/standardpanel.cpp
index bf81375..0d76a5a 100644
--- a/modules/gui/qt4/components/playlist/standardpanel.cpp
+++ b/modules/gui/qt4/components/playlist/standardpanel.cpp
@@ -455,19 +455,21 @@ LocationBar::LocationBar( PLModel *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 );
+ btnMore = new LocationButton( "...", false, true, this );
+ menuMore = new QMenu( this );
+ btnMore->setMenu( menuMore );
}
void LocationBar::setIndex( const QModelIndex &index )
{
qDeleteAll( buttons );
buttons.clear();
+ qDeleteAll( actions );
+ actions.clear();
+
QModelIndex i = index;
- bool bold = true;
- box->addStretch();
+ bool first = true;
+
while( true )
{
PLItem *item = model->getItem( i );
@@ -475,19 +477,32 @@ void LocationBar::setIndex( const QModelIndex &index )
char *fb_name = input_item_GetTitleFbName( item->inputItem() );
QString text = qfu(fb_name);
free(fb_name);
- QAbstractButton *btn = new LocationButton( text, bold, i.isValid() );
+
+ QAbstractButton *btn = new LocationButton( text, first, !first, this );
btn->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Fixed );
- box->insertWidget( 0, btn );
buttons.append( btn );
- mapper->setMapping( btn, item->id() );
- CONNECT( btn, clicked( ), mapper, map( ) );
+ QAction *action = new QAction( text, this );
+ actions.append( action );
+ CONNECT( btn, clicked(), action, trigger() );
- bold = false;
+ mapper->setMapping( action, item->id() );
+ CONNECT( action, triggered(), mapper, map() );
+
+ first = false;
if( i.isValid() ) i = i.parent();
else break;
}
+
+ QString prefix;
+ for( int a = actions.count() - 1; a >= 0 ; a-- )
+ {
+ actions[a]->setText( prefix + actions[a]->text() );
+ prefix += QString(" ");
+ }
+
+ if( isVisible() ) layOut( size() );
}
void LocationBar::setRootIndex()
@@ -501,8 +516,77 @@ void LocationBar::invoke( int i_id )
emit invoked ( index );
}
-LocationButton::LocationButton( const QString &text, bool bold, bool arrow )
- : b_arrow( arrow )
+void LocationBar::layOut( const QSize& size )
+{
+ menuMore->clear();
+
+ int count = buttons.count();
+ QList<int> widths;
+ int totalWidth = 0;
+ for( int i = 0; i < count; i++ )
+ {
+ int w = buttons[i]->sizeHint().width();
+ if( i == 0 || totalWidth + w <= size.width() )
+ {
+ totalWidth += w;
+ widths.append( w );
+ }
+ if( totalWidth > size.width() ) break;
+ }
+
+ int x = 0;
+ int shown = widths.count();
+ if( shown < count )
+ {
+ QSize sz = btnMore->sizeHint();
+ btnMore->setGeometry( 0, 0, sz.width(), size.height() );
+ btnMore->show();
+ x = sz.width();
+ totalWidth += x;
+ }
+ else
+ {
+ btnMore->hide();
+ }
+ shown--;
+ for( int i = count - 1; i >= 0; i-- )
+ {
+ if( i > shown )
+ {
+ menuMore->addAction( actions[i] );
+ buttons[i]->hide();
+ }
+ else if( i > 0 && totalWidth > size.width() )
+ {
+ menuMore->addAction( actions[i] );
+ buttons[i]->hide();
+ totalWidth -= widths[i];
+ }
+ else
+ {
+ buttons[i]->setGeometry( x, 0,
+ qMin( widths[i], size.width() - x ),
+ size.height() );
+ buttons[i]->show();
+ totalWidth -= widths[i];
+ x += widths[i];
+ }
+ }
+}
+
+void LocationBar::resizeEvent ( QResizeEvent * event )
+{
+ layOut( event->size() );
+}
+
+QSize LocationBar::sizeHint() const
+{
+ return btnMore->sizeHint();
+}
+
+LocationButton::LocationButton( const QString &text, bool bold,
+ bool arrow, QWidget * parent )
+ : b_arrow( arrow ), QPushButton( parent )
{
QFont font;
font.setBold( bold );
@@ -520,35 +604,41 @@ void LocationButton::paintEvent ( QPaintEvent * event )
QPainter p( this );
if( underMouse() )
- style()->drawControl( QStyle::CE_PushButtonBevel, &option, &p );
-
- int margin = style()->pixelMetric(QStyle::PM_DefaultFrameWidth,0,this) + PADDING;
+ {
+ p.save();
+ p.setRenderHint( QPainter::Antialiasing, true );
+ QColor c = palette().color( QPalette::Highlight );
+ p.setPen( c );
+ p.setBrush( c.lighter( 150 ) );
+ p.setOpacity( 0.2 );
+ p.drawRoundedRect( option.rect.adjusted( 0, 2, 0, -2 ), 5, 5 );
+ p.restore();
+ }
- QRect rect = option.rect.adjusted( b_arrow ? 15 + margin : margin, 0, -margin, 0 );
+ QRect r = option.rect.adjusted( PADDING, 0, -PADDING - (b_arrow ? 10 : 0), 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( r.width() < fontMetrics().boundingRect( text() ).width() )
+ str = fontMetrics().elidedText( text(), Qt::ElideRight, r.width() );
+ p.drawText( r, Qt::AlignVCenter | Qt::AlignLeft, str );
if( b_arrow )
{
- option.rect.setX( margin );
- option.rect.setWidth( 8 );
+ option.rect.setWidth( 10 );
+ option.rect.moveRight( rect().right() );
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() );
+ s.setWidth( s.width() + ( 2 * PADDING ) + ( b_arrow ? 10 : 0 ) + 2 );
+ s.setHeight( s.height() + 2 * PADDING );
return s;
}
diff --git a/modules/gui/qt4/components/playlist/standardpanel.hpp b/modules/gui/qt4/components/playlist/standardpanel.hpp
index 6885f82..66fb613 100644
--- a/modules/gui/qt4/components/playlist/standardpanel.hpp
+++ b/modules/gui/qt4/components/playlist/standardpanel.hpp
@@ -117,12 +117,24 @@ private slots:
void browseInto( input_item_t * );
};
+class LocationButton : public QPushButton
+{
+public:
+ LocationButton( const QString &, bool bold, bool arrow, QWidget * parent = NULL );
+ QSize sizeHint() const;
+private:
+ void paintEvent ( QPaintEvent * event );
+ QFontMetrics *metrics;
+ bool b_arrow;
+};
+
class LocationBar : public QWidget
{
Q_OBJECT;
public:
LocationBar( PLModel * );
void setIndex( const QModelIndex & );
+ QSize sizeHint() const;
signals:
void invoked( const QModelIndex & );
public slots:
@@ -130,21 +142,16 @@ public slots:
private slots:
void invoke( int i_item_id );
private:
+ void layOut( const QSize& size );
+ void resizeEvent ( QResizeEvent * event );
+
PLModel *model;
QSignalMapper *mapper;
QHBoxLayout *box;
QList<QWidget*> buttons;
-};
-
-class LocationButton : public QPushButton
-{
-public:
- LocationButton( const QString &, bool bold, bool arrow );
-private:
- void paintEvent ( QPaintEvent * event );
- QSize sizeHint() const;
- QFontMetrics *metrics;
- bool b_arrow;
+ QList<QAction*> actions;
+ LocationButton *btnMore;
+ QMenu *menuMore;
};
#endif
More information about the vlc-devel
mailing list