mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-27 19:24:08 +00:00
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:
parent
83acbcf10c
commit
354066c292
119
mainstatusbar.cc
119
mainstatusbar.cc
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
16
qt-style.css
16
qt-style.css
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue