Reimplemented the status bar as internal widget instead of top-level borderless window.

Now the status bar behavior is much more reliable on X11 systems, no more
lags when moving GoldenDict window around or when resizing it. Works
better with compositing window managers as well.

Also, the new status bar also supports images, which is good for
warnings and error messages.

The status bar is fully styled and can change its appearence
based on user's CSS, if needed.
This commit is contained in:
Tvangeste 2011-07-09 13:55:44 +02:00
parent 83acbcf10c
commit 354066c292
4 changed files with 70 additions and 85 deletions

View file

@ -8,126 +8,89 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QDebug> #include <QDebug>
#include <QEvent> #include <QEvent>
#include <QApplication>
MainStatusBar::MainStatusBar(QWidget *parent) : QFrame(parent) MainStatusBar::MainStatusBar(QWidget *parent) : QWidget(parent)
{ {
// style textWidget = new QLabel(QString(), this);
setWindowFlags( Qt::Tool | Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint ); textWidget->setObjectName("text");
setFrameStyle( QFrame::Box | QFrame::Plain ); textWidget->setFont(QApplication::font("QStatusBar"));
setLineWidth(0); textWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
picWidget = new QLabel(QString(), this);
picWidget->setObjectName("icon");
picWidget->setPixmap(QPixmap());
picWidget->setScaledContents(true);
picWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
// components
label = new QLabel(QString(), this);
label->setTextFormat(Qt::PlainText);
timer = new QTimer(this); timer = new QTimer(this);
// layout // layout
QVBoxLayout * layout = new QVBoxLayout; QHBoxLayout * layout = new QHBoxLayout;
layout->addWidget(label); layout->setSpacing(0);
layout->setSizeConstraint(QLayout::SetFixedSize); layout->setSizeConstraint(QLayout::SetFixedSize);
layout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); layout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
layout->setMargin(4); layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(picWidget);
layout->addWidget(textWidget);
setLayout(layout); setLayout(layout);
parentWidget()->installEventFilter( this );
connect( timer, SIGNAL( timeout() ), SLOT( clearMessage() ) ); connect( timer, SIGNAL( timeout() ), SLOT( clearMessage() ) );
} }
void MainStatusBar::clearMessage() void MainStatusBar::clearMessage()
{ {
message = QString(); textWidget->setText(QString());
label->setText(message); picWidget->setPixmap(QPixmap());
timer->stop(); timer->stop();
refresh(); refresh();
} }
QString MainStatusBar::currentMessage() const QString MainStatusBar::currentMessage() const
{ {
return message; return textWidget->text();
} }
void MainStatusBar::showMessage(const QString & str, int timeout) void MainStatusBar::showMessage(const QString & str, int timeout, const QPixmap & pixmap)
{ {
message = str; textWidget->setText( str );
picWidget->setPixmap( pixmap );
if ( timeout > 0 ) if ( timeout > 0 )
{
timer->start( timeout );
}
refresh();
}
void MainStatusBar::refresh(bool forceHide)
{
if ( forceHide )
{ {
hide(); timer->start( timeout );
return;
} }
if ( !message.isEmpty() ) refresh();
{ }
int maxLabelLength = parentWidget()->width() - 2 * layout()->margin(); void MainStatusBar::refresh()
label->setText( label->fontMetrics().elidedText( message, Qt::ElideRight, maxLabelLength ) ); {
if ( !currentMessage().isEmpty() )
{
if ( !picWidget->pixmap()->isNull() )
{
picWidget->setFixedSize( textWidget->height(), textWidget->height() );
}
else
{
picWidget->setFixedSize( 0, 0);
}
adjustSize(); adjustSize();
// move(pGeom.left(), pGeom.bottom() - size().height() + 1 ); move( QPoint( 0, parentWidget()->height() - height() ) );
move(parentWidget()->mapToGlobal(QPoint(0, parentWidget()->height() - height() + 1)));
if ( parentWidget()->isHidden() )
{
hide();
return;
}
if ( parentWidget()->isMinimized() )
{
hide();
return;
}
show(); show();
raise();
} }
else else
{ {
hide(); hide();
} }
} }
void MainStatusBar::mousePressEvent ( QMouseEvent * ) void MainStatusBar::mousePressEvent ( QMouseEvent * )
{ {
clearMessage(); clearMessage();
} }
bool MainStatusBar::eventFilter(QObject *, QEvent * e)
{
switch ( e->type() ) {
case QEvent::Hide:
case QEvent::WindowDeactivate:
#ifdef Q_WS_X11
// workaround for X11 idiosyncrasies
// qDebug() << e->type();
refresh(true);
break;
#endif
case QEvent::Resize:
case QEvent::FocusOut:
case QEvent::Move:
case QEvent::WindowStateChange:
case QEvent::WindowActivate:
// qDebug() << e->type();
refresh();
break;
default:
break;
};
return false;
}

View file

@ -9,7 +9,7 @@
#include <QString> #include <QString>
#include <QTimer> #include <QTimer>
class MainStatusBar : public QFrame class MainStatusBar : public QWidget
{ {
Q_OBJECT Q_OBJECT
@ -20,18 +20,21 @@ public:
signals: signals:
public slots: public slots:
void showMessage(const QString & text, int timeout = 0); void showMessage(const QString & text, int timeout = 0, const QPixmap & pixmap = QPixmap());
void clearMessage(); void clearMessage();
protected: protected:
virtual void mousePressEvent(QMouseEvent * event); virtual void mousePressEvent(QMouseEvent * event);
private: private:
QLabel * label; // component to display a small picture
QLabel * picWidget;
// component to display text
QLabel * textWidget;
QTimer * timer; QTimer * timer;
QString message; void refresh();
bool eventFilter(QObject *obj, QEvent * event);
void refresh(bool forceHide = false);
}; };
#endif // MAINSTATUSBAR_HH #endif // MAINSTATUSBAR_HH

View file

@ -2110,7 +2110,10 @@ void MainWindow::toggleMenuBarTriggered(bool announce)
if ( cfg.preferences.hideMenubar ) if ( cfg.preferences.hideMenubar )
{ {
mainStatusBar->showMessage( mainStatusBar->showMessage(
tr( "You have chosen to hide a menubar. Use %1 to show it back." ).arg( tr( "Ctrl+M" ) ), 10000 ); tr( "You have chosen to hide a menubar. Use %1 to show it back." )
.arg( QString( "<b>%1</b>" ) ).arg( tr( "Ctrl+M" ) ),
10000,
QPixmap( ":/icons/warning.png" ) );
} }
else else
{ {

View file

@ -19,4 +19,20 @@ ArticleView #searchText[noResults="true"]
border: 1px solid grey; border: 1px solid grey;
} }
MainStatusBar #text
{
border-top-right-radius: 3px;
border-top: 1px solid palette(dark);
border-right: 1px solid palette(dark);
background: palette(window);
padding: 2px;
}
MainStatusBar #icon
{
border-top: 1px solid palette(dark);
background: palette(window);
padding: 2px;
padding-left: 4px;
padding-right: 0px;
}