Commit beec0722 authored by Jakob Leben's avatar 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.
parent d536e2bb
...@@ -455,19 +455,21 @@ LocationBar::LocationBar( PLModel *m ) ...@@ -455,19 +455,21 @@ LocationBar::LocationBar( PLModel *m )
mapper = new QSignalMapper( this ); mapper = new QSignalMapper( this );
CONNECT( mapper, mapped( int ), this, invoke( int ) ); CONNECT( mapper, mapped( int ), this, invoke( int ) );
box = new QHBoxLayout; btnMore = new LocationButton( "...", false, true, this );
box->setSpacing( 0 ); menuMore = new QMenu( this );
box->setContentsMargins( 0, 0, 0, 0 ); btnMore->setMenu( menuMore );
setLayout( box );
} }
void LocationBar::setIndex( const QModelIndex &index ) void LocationBar::setIndex( const QModelIndex &index )
{ {
qDeleteAll( buttons ); qDeleteAll( buttons );
buttons.clear(); buttons.clear();
qDeleteAll( actions );
actions.clear();
QModelIndex i = index; QModelIndex i = index;
bool bold = true; bool first = true;
box->addStretch();
while( true ) while( true )
{ {
PLItem *item = model->getItem( i ); PLItem *item = model->getItem( i );
...@@ -475,19 +477,32 @@ void LocationBar::setIndex( const QModelIndex &index ) ...@@ -475,19 +477,32 @@ void LocationBar::setIndex( const QModelIndex &index )
char *fb_name = input_item_GetTitleFbName( item->inputItem() ); char *fb_name = input_item_GetTitleFbName( item->inputItem() );
QString text = qfu(fb_name); QString text = qfu(fb_name);
free(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 ); btn->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Fixed );
box->insertWidget( 0, btn );
buttons.append( btn ); buttons.append( btn );
mapper->setMapping( btn, item->id() ); QAction *action = new QAction( text, this );
CONNECT( btn, clicked( ), mapper, map( ) ); 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(); if( i.isValid() ) i = i.parent();
else break; 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() void LocationBar::setRootIndex()
...@@ -501,8 +516,77 @@ void LocationBar::invoke( int i_id ) ...@@ -501,8 +516,77 @@ void LocationBar::invoke( int i_id )
emit invoked ( index ); emit invoked ( index );
} }
LocationButton::LocationButton( const QString &text, bool bold, bool arrow ) void LocationBar::layOut( const QSize& size )
: b_arrow( arrow ) {
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; QFont font;
font.setBold( bold ); font.setBold( bold );
...@@ -520,35 +604,41 @@ void LocationButton::paintEvent ( QPaintEvent * event ) ...@@ -520,35 +604,41 @@ void LocationButton::paintEvent ( QPaintEvent * event )
QPainter p( this ); QPainter p( this );
if( underMouse() ) if( underMouse() )
style()->drawControl( QStyle::CE_PushButtonBevel, &option, &p ); {
p.save();
int margin = style()->pixelMetric(QStyle::PM_DefaultFrameWidth,0,this) + PADDING; 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() ); QString str( text() );
/* This check is absurd, but either it is not done properly inside elidedText(), /* This check is absurd, but either it is not done properly inside elidedText(),
or boundingRect() is wrong */ or boundingRect() is wrong */
if( rect.width() < fontMetrics().boundingRect( text() ).width() ) if( r.width() < fontMetrics().boundingRect( text() ).width() )
str = fontMetrics().elidedText( text(), Qt::ElideRight, rect.width() ); str = fontMetrics().elidedText( text(), Qt::ElideRight, r.width() );
p.drawText( rect, Qt::AlignVCenter | Qt::AlignLeft, str ); p.drawText( r, Qt::AlignVCenter | Qt::AlignLeft, str );
if( b_arrow ) if( b_arrow )
{ {
option.rect.setX( margin ); option.rect.setWidth( 10 );
option.rect.setWidth( 8 ); option.rect.moveRight( rect().right() );
style()->drawPrimitive( QStyle::PE_IndicatorArrowRight, &option, &p ); style()->drawPrimitive( QStyle::PE_IndicatorArrowRight, &option, &p );
} }
} }
QSize LocationButton::sizeHint() const QSize LocationButton::sizeHint() const
{ {
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth,0,this);
QSize s( fontMetrics().boundingRect( text() ).size() ); QSize s( fontMetrics().boundingRect( text() ).size() );
/* Add two pixels to width: font metrics are buggy, if you pass text through elidation /* 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 */ 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.setWidth( s.width() + ( 2 * PADDING ) + ( b_arrow ? 10 : 0 ) + 2 );
s.setHeight( QPushButton::sizeHint().height() ); s.setHeight( s.height() + 2 * PADDING );
return s; return s;
} }
......
...@@ -117,12 +117,24 @@ private slots: ...@@ -117,12 +117,24 @@ private slots:
void browseInto( input_item_t * ); 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 class LocationBar : public QWidget
{ {
Q_OBJECT; Q_OBJECT;
public: public:
LocationBar( PLModel * ); LocationBar( PLModel * );
void setIndex( const QModelIndex & ); void setIndex( const QModelIndex & );
QSize sizeHint() const;
signals: signals:
void invoked( const QModelIndex & ); void invoked( const QModelIndex & );
public slots: public slots:
...@@ -130,21 +142,16 @@ public slots: ...@@ -130,21 +142,16 @@ public slots:
private slots: private slots:
void invoke( int i_item_id ); void invoke( int i_item_id );
private: private:
void layOut( const QSize& size );
void resizeEvent ( QResizeEvent * event );
PLModel *model; PLModel *model;
QSignalMapper *mapper; QSignalMapper *mapper;
QHBoxLayout *box; QHBoxLayout *box;
QList<QWidget*> buttons; QList<QWidget*> buttons;
}; QList<QAction*> actions;
LocationButton *btnMore;
class LocationButton : public QPushButton QMenu *menuMore;
{
public:
LocationButton( const QString &, bool bold, bool arrow );
private:
void paintEvent ( QPaintEvent * event );
QSize sizeHint() const;
QFontMetrics *metrics;
bool b_arrow;
}; };
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment