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 <QDebug>
#include <QEvent>
#include <QApplication>
MainStatusBar::MainStatusBar(QWidget *parent) : QFrame(parent)
MainStatusBar::MainStatusBar(QWidget *parent) : QWidget(parent)
{
// style
setWindowFlags( Qt::Tool | Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint );
setFrameStyle( QFrame::Box | QFrame::Plain );
setLineWidth(0);
textWidget = new QLabel(QString(), this);
textWidget->setObjectName("text");
textWidget->setFont(QApplication::font("QStatusBar"));
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);
// layout
QVBoxLayout * layout = new QVBoxLayout;
layout->addWidget(label);
QHBoxLayout * layout = new QHBoxLayout;
layout->setSpacing(0);
layout->setSizeConstraint(QLayout::SetFixedSize);
layout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
layout->setMargin(4);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(picWidget);
layout->addWidget(textWidget);
setLayout(layout);
parentWidget()->installEventFilter( this );
connect( timer, SIGNAL( timeout() ), SLOT( clearMessage() ) );
}
void MainStatusBar::clearMessage()
{
message = QString();
label->setText(message);
textWidget->setText(QString());
picWidget->setPixmap(QPixmap());
timer->stop();
refresh();
}
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 )
{
timer->start( timeout );
}
refresh();
}
void MainStatusBar::refresh(bool forceHide)
{
if ( forceHide )
if ( timeout > 0 )
{
hide();
return;
timer->start( timeout );
}
if ( !message.isEmpty() )
{
refresh();
}
int maxLabelLength = parentWidget()->width() - 2 * layout()->margin();
label->setText( label->fontMetrics().elidedText( message, Qt::ElideRight, maxLabelLength ) );
void MainStatusBar::refresh()
{
if ( !currentMessage().isEmpty() )
{
if ( !picWidget->pixmap()->isNull() )
{
picWidget->setFixedSize( textWidget->height(), textWidget->height() );
}
else
{
picWidget->setFixedSize( 0, 0);
}
adjustSize();
// move(pGeom.left(), pGeom.bottom() - size().height() + 1 );
move(parentWidget()->mapToGlobal(QPoint(0, parentWidget()->height() - height() + 1)));
if ( parentWidget()->isHidden() )
{
hide();
return;
}
if ( parentWidget()->isMinimized() )
{
hide();
return;
}
move( QPoint( 0, parentWidget()->height() - height() ) );
show();
raise();
}
else
{
hide();
}
}
void MainStatusBar::mousePressEvent ( QMouseEvent * )
{
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 <QTimer>
class MainStatusBar : public QFrame
class MainStatusBar : public QWidget
{
Q_OBJECT
@ -20,18 +20,21 @@ public:
signals:
public slots:
void showMessage(const QString & text, int timeout = 0);
void showMessage(const QString & text, int timeout = 0, const QPixmap & pixmap = QPixmap());
void clearMessage();
protected:
virtual void mousePressEvent(QMouseEvent * event);
private:
QLabel * label;
// component to display a small picture
QLabel * picWidget;
// component to display text
QLabel * textWidget;
QTimer * timer;
QString message;
bool eventFilter(QObject *obj, QEvent * event);
void refresh(bool forceHide = false);
void refresh();
};
#endif // MAINSTATUSBAR_HH

View file

@ -2110,7 +2110,10 @@ void MainWindow::toggleMenuBarTriggered(bool announce)
if ( cfg.preferences.hideMenubar )
{
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
{

View file

@ -19,4 +19,20 @@ ArticleView #searchText[noResults="true"]
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;
}