mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-22 03:26:05 -04:00
Fixes #693: Draw tab title with gradient to fade-out
This commit is contained in:
parent
018f619a5e
commit
d883958ec4
@ -136,9 +136,7 @@ QTabBar::tab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QTabBar::tab:selected {
|
QTabBar::tab:selected {
|
||||||
/* please keep it in sync with 'selected_tab_bg_color' in src/tabbar.cpp */
|
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|
||||||
border-bottom: 2px solid white;
|
border-bottom: 2px solid white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
153
src/tabbar.cpp
153
src/tabbar.cpp
@ -155,35 +155,28 @@ void TabBar::openUrl(const QUrl& url, bool newTab)
|
|||||||
void TabBar::setTitleOf(const QString& title, ZimView* tab)
|
void TabBar::setTitleOf(const QString& title, ZimView* tab)
|
||||||
{
|
{
|
||||||
CURRENTIFNULL(tab);
|
CURRENTIFNULL(tab);
|
||||||
|
int idx = mp_stackedWidget->indexOf(tab);
|
||||||
|
if (idx < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QString t = title;
|
||||||
|
|
||||||
if (title.startsWith("zim://")) {
|
if (title.startsWith("zim://")) {
|
||||||
auto url = QUrl(title);
|
auto url = QUrl(title);
|
||||||
setTabText(mp_stackedWidget->indexOf(tab), url.path());
|
t = url.path();
|
||||||
} else {
|
|
||||||
int idx = mp_stackedWidget->indexOf(tab);
|
|
||||||
setTabToolTip(idx, title);
|
|
||||||
|
|
||||||
// This logic is taken from the implementation:
|
|
||||||
// <QTDIR>/5.12.6/Src/qtbase/src/widgets/widgets/qtabbar.cpp
|
|
||||||
// void QTabBar::initStyleOption(QStyleOptionTab *option, int tabIndex) const
|
|
||||||
QStyleOptionTab tab;
|
|
||||||
initStyleOption(&tab, idx);
|
|
||||||
QRect textRect = style()->subElementRect(QStyle::SE_TabBarTabText, &tab, this);
|
|
||||||
|
|
||||||
// but instead of eliding text as QTabBar::initStyleOption() does
|
|
||||||
// we cut it and store the flag if it was cut
|
|
||||||
QString cut = fontMetrics().elidedText(title, Qt::ElideRight, textRect.width());
|
|
||||||
// strip ... from the end (this three dots are one char)
|
|
||||||
if (cut.size() < title.size()) {
|
|
||||||
cut = cut.mid(0, cut.size() - 1);
|
|
||||||
// set flag that the text was too long, was cut and this tab
|
|
||||||
// need 'fade out' effect while drawing
|
|
||||||
setTabData(idx, QVariant::fromValue(true));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
setTabData(idx, QVariant::fromValue(false));
|
|
||||||
}
|
|
||||||
setTabText(idx, cut);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTabToolTip(idx, t);
|
||||||
|
|
||||||
|
/* we don't use setTabText() because Qt can't draw text with
|
||||||
|
* fade-out gradient selectively (only for large texts).
|
||||||
|
* So we just store tab's title, and will draw it later ourselves.
|
||||||
|
*/
|
||||||
|
setTabData(idx, QVariant::fromValue(t));
|
||||||
|
|
||||||
|
// need to initiate repaint
|
||||||
|
// because setTabData() didn't do it as setTabText() before.
|
||||||
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabBar::setIconOf(const QIcon &icon, ZimView *tab)
|
void TabBar::setIconOf(const QIcon &icon, ZimView *tab)
|
||||||
@ -361,73 +354,73 @@ void TabBar::mousePressEvent(QMouseEvent *event)
|
|||||||
|
|
||||||
void TabBar::paintEvent(QPaintEvent *e)
|
void TabBar::paintEvent(QPaintEvent *e)
|
||||||
{
|
{
|
||||||
// Please keep it in sync with resources/css/style.css
|
/* first, let Qt draw QTabBar normally.
|
||||||
// QTabBar::tab:selected { background-color: <value> }
|
* QTabbar will leave tabs titles empty because we didn't set these values into QTabBar.
|
||||||
const QColor selected_tab_bg_color = QColor(Qt::white);
|
*/
|
||||||
|
|
||||||
// first, let Qt draw QTabBar normally
|
|
||||||
QTabBar::paintEvent(e);
|
QTabBar::paintEvent(e);
|
||||||
|
|
||||||
// Then apply fade-out effect for long tab title on top:
|
// Then, for each tab, we draw titles, using fade-out effect when needed.
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
|
|
||||||
for (int i = 0; i < count(); ++i) {
|
for (int i = 0; i < count(); ++i) {
|
||||||
bool need_fade_out = tabData(i).toBool();
|
QString tab_title = tabData(i).toString();
|
||||||
if (! need_fade_out)
|
if (tab_title.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QStyleOptionTab tab;
|
/* See the implementation of QTabBar for better understanding this code:
|
||||||
initStyleOption(&tab, i);
|
* <QTDIR>/5.12.6/Src/qtbase/src/widgets/widgets/qtabbar.cpp
|
||||||
|
* in particular, QTabBar::initStyleOption()
|
||||||
QRect textRect = style()->subElementRect(QStyle::SE_TabBarTabText, &tab, this);
|
|
||||||
|
|
||||||
QRect tail = textRect;
|
|
||||||
tail.setWidth(textRect.width() * 0.2);
|
|
||||||
|
|
||||||
// isRightToLeft() gives inherrited from application layout direction,
|
|
||||||
// but we need the direction of each individual tab header text here
|
|
||||||
bool right_to_left = tabText(i).isRightToLeft();
|
|
||||||
|
|
||||||
if (! right_to_left) {
|
|
||||||
// Normal left-to-right text layout: move fading-out box to the right
|
|
||||||
tail.moveRight(textRect.right());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool selected = tab.state & QStyle::State_Selected;
|
|
||||||
|
|
||||||
/* This gets the color from our style.css rule:
|
|
||||||
* QWidget {
|
|
||||||
* background-color: #EAECF0;
|
|
||||||
* }
|
|
||||||
*/
|
*/
|
||||||
QColor c0 = tab.palette.background().color();
|
QStyleOptionTab tabopt;
|
||||||
|
initStyleOption(&tabopt, i);
|
||||||
|
|
||||||
if (selected) {
|
bool need_fade_out = false;
|
||||||
/* We cannot just get back from QStyleSheetStyle (Qt private classes)
|
|
||||||
* the value of QTabBar::tab:selected { background-color: <value> }
|
QRect tabTextRect = style()->subElementRect(QStyle::SE_TabBarTabText, &tabopt, this);
|
||||||
* so have to use hard-coded value here:
|
|
||||||
*/
|
QRect fontTextRect = fontMetrics().boundingRect(tab_title);
|
||||||
c0 = selected_tab_bg_color;
|
|
||||||
|
if (fontTextRect.width() > tabTextRect.width())
|
||||||
|
need_fade_out = true;
|
||||||
|
|
||||||
|
bool right_to_left = tab_title.isRightToLeft();
|
||||||
|
|
||||||
|
if (need_fade_out) {
|
||||||
|
// draw the most of tab text extent with the normal color,
|
||||||
|
// and draw the rest with alpha channel gradient
|
||||||
|
QColor c0 = tabopt.palette.brush(QPalette::ButtonText).color();
|
||||||
|
QColor c1(c0);
|
||||||
|
|
||||||
|
c0.setAlpha(255); // color of font
|
||||||
|
c1.setAlpha(0); // transparent
|
||||||
|
|
||||||
|
const int mid_Y = tabTextRect.center().y();
|
||||||
|
QLinearGradient gr;
|
||||||
|
|
||||||
|
if (right_to_left) {
|
||||||
|
// arabic right-to-left text
|
||||||
|
gr.setStart(tabTextRect.x(), mid_Y);
|
||||||
|
gr.setFinalStop(tabTextRect.x() + 0.2 * tabTextRect.width(), mid_Y);
|
||||||
|
gr.setColorAt(0.0, c1);
|
||||||
|
gr.setColorAt(1.0, c0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// normal left-to-right text direction
|
||||||
|
gr.setStart(tabTextRect.x() + 0.8 * tabTextRect.width(), mid_Y);
|
||||||
|
gr.setFinalStop(tabTextRect.right(), mid_Y);
|
||||||
|
gr.setColorAt(0.0, c0);
|
||||||
|
gr.setColorAt(1.0, c1);
|
||||||
|
}
|
||||||
|
tabopt.palette.setBrush(QPalette::ButtonText, QBrush(gr));
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor c1(c0);
|
int align = Qt::AlignVCenter;
|
||||||
|
if (need_fade_out) {
|
||||||
if (right_to_left) {
|
align |= (right_to_left)? Qt::AlignRight : Qt::AlignLeft;
|
||||||
c0.setAlpha(255);
|
|
||||||
c1.setAlpha(0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
c0.setAlpha(0);
|
|
||||||
c1.setAlpha(255);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QLinearGradient gr(tail.topLeft(), tail.topRight());
|
style()->drawItemText(&p, tabTextRect, align,
|
||||||
gr.setSpread(QGradient::PadSpread);
|
tabopt.palette, true, tab_title, QPalette::ButtonText);
|
||||||
gr.setColorAt(0.0, c0);
|
|
||||||
gr.setColorAt(1.0, c1);
|
|
||||||
|
|
||||||
QBrush br(gr);
|
|
||||||
p.fillRect(tail, br);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user