From bb747e129046631ecfbdb47dfd2381b223f4ee40 Mon Sep 17 00:00:00 2001 From: "craig.p.drummond" Date: Tue, 19 Feb 2013 16:49:40 +0000 Subject: [PATCH] Overlay-ish looking scrollbars for ambiance theme. --- ChangeLog | 1 + gui/gtkproxystyle.cpp | 164 +++++++++++++++++++++++++++++++++++++++++- gui/gtkproxystyle.h | 5 ++ gui/mainwindow.cpp | 2 +- 4 files changed, 170 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index bbf098a3d..a9d0eba62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -103,6 +103,7 @@ 58. Improve look of Gtk3 style spinbox. 59. Use xdg-open for "Open In File Manager" action of folder page. 60. When searching for album information, use the album-artist of the track. +61. Overlay-ish looking scrollbars for ambiance theme. 0.9.2 ----- diff --git a/gui/gtkproxystyle.cpp b/gui/gtkproxystyle.cpp index 30946694b..c03957c98 100644 --- a/gui/gtkproxystyle.cpp +++ b/gui/gtkproxystyle.cpp @@ -22,19 +22,24 @@ */ #include "gtkproxystyle.h" +#include "gtkstyle.h" #include #include #include +#include GtkProxyStyle::GtkProxyStyle() : QProxyStyle() { + slimScrollbars=GtkStyle::themeName().toLower()==QLatin1String("ambiance"); setBaseStyle(qApp->style()); toolbarCombo=new QComboBox(new QToolBar()); } QSize GtkProxyStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const { + QSize sz=baseStyle()->sizeFromContents(type, option, size, widget); + if (CT_ComboBox==type && widget && widget->parentWidget() && QString(widget->parentWidget()->metaObject()->className()).endsWith("Page")) { QSize orig=baseStyle()->sizeFromContents(type, option, size, widget); QSize other=baseStyle()->sizeFromContents(type, option, size, toolbarCombo); @@ -42,6 +47,163 @@ QSize GtkProxyStyle::sizeFromContents(ContentsType type, const QStyleOption *opt return QSize(orig.width(), other.height()); } return orig; + } else if (slimScrollbars && CT_ScrollBar==type) { + if (const QStyleOptionSlider *sb = qstyleoption_cast(option)) { + int extent(pixelMetric(PM_ScrollBarExtent, option, widget)), + sliderMin(pixelMetric(PM_ScrollBarSliderMin, option, widget)); + + if (sb->orientation == Qt::Horizontal) { + sz = QSize(sliderMin, extent); + } else { + sz = QSize(extent, sliderMin); + } + } } - return baseStyle()->sizeFromContents(type, option, size, widget); + return sz; +} + +int GtkProxyStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const +{ + if (slimScrollbars && SH_ScrollView_FrameOnlyAroundContents==hint) { + return false; + } + + return baseStyle()->styleHint(hint, option, widget, returnData); +} + +int GtkProxyStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const +{ + if (slimScrollbars && PM_ScrollBarExtent==metric) { + return (option ? option->fontMetrics.height() : QApplication::fontMetrics().height())/1.75; + } + return baseStyle()->pixelMetric(metric, option, widget); +} + +QRect GtkProxyStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const +{ + if (slimScrollbars && CC_ScrollBar==control) { + if (const QStyleOptionSlider *sb = qstyleoption_cast(option)) { + QRect ret; + bool horizontal(Qt::Horizontal==sb->orientation); + int sbextent(pixelMetric(PM_ScrollBarExtent, sb, widget)), + sliderMaxLength(horizontal ? sb->rect.width() : sb->rect.height()), + sliderMinLength(pixelMetric(PM_ScrollBarSliderMin, sb, widget)), + sliderLength; + + if (sb->maximum != sb->minimum) { + uint valueRange = sb->maximum - sb->minimum; + sliderLength = (sb->pageStep * sliderMaxLength) / (valueRange + sb->pageStep); + + if (sliderLength < sliderMinLength) { + sliderLength = sliderMinLength; + } + if (sliderLength > sliderMaxLength) { + sliderLength = sliderMaxLength; + } + } else { + sliderLength = sliderMaxLength; + } + + int sliderstart(sliderPositionFromValue(sb->minimum, sb->maximum, sb->sliderPosition, sliderMaxLength - sliderLength, sb->upsideDown)); + + // Subcontrols + switch(subControl) + { + case SC_ScrollBarSubLine: + case SC_ScrollBarAddLine: + return QRect(); + case SC_ScrollBarSubPage: + if (horizontal) { + ret.setRect(0, 0, sliderstart, sbextent); + } else { + ret.setRect(0, 0, sbextent, sliderstart); + } + break; + case SC_ScrollBarAddPage: + if (horizontal) { + ret.setRect(sliderstart + sliderLength, 0, sliderMaxLength - sliderstart - sliderLength, sbextent); + } else { + ret.setRect(0, sliderstart + sliderLength, sbextent, sliderMaxLength - sliderstart - sliderLength); + } + break; + case SC_ScrollBarGroove: + if (horizontal) { + ret=QRect(0, 0, sb->rect.width(), sb->rect.height()); + } else { + ret=QRect(0, 0, sb->rect.width(), sb->rect.height()); + } + break; + case SC_ScrollBarSlider: + if (horizontal) { + ret=QRect(sliderstart, 0, sliderLength, sbextent); + } else { + ret=QRect(0, sliderstart, sbextent, sliderLength); + } + break; + default: + ret = baseStyle()->subControlRect(control, option, subControl, widget); + break; + } + return visualRect(sb->direction/*Qt::LeftToRight*/, sb->rect, ret); + } + } + return baseStyle()->subControlRect(control, option, subControl, widget); +} + +static QPainterPath buildPath(const QRectF &r, double radius) +{ + QPainterPath path; + double diameter(radius*2); + + path.moveTo(r.x()+r.width(), r.y()+r.height()-radius); + path.arcTo(r.x()+r.width()-diameter, r.y(), diameter, diameter, 0, 90); + path.arcTo(r.x(), r.y(), diameter, diameter, 90, 90); + path.arcTo(r.x(), r.y()+r.height()-diameter, diameter, diameter, 180, 90); + path.arcTo(r.x()+r.width()-diameter, r.y()+r.height()-diameter, diameter, diameter, 270, 90); + return path; +} + +void GtkProxyStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const +{ + if (slimScrollbars && CC_ScrollBar==control) { + if (const QStyleOptionSlider *sb = qstyleoption_cast(option)) { + QRect r=option->rect; + QRect slider=subControlRect(control, option, SC_ScrollBarSlider, widget); + painter->save(); + painter->fillRect(r, option->palette.base()); + QColor col=option->palette.foreground().color(); + col.setAlphaF(0.15); + painter->setPen(col); + if (Qt::Horizontal==sb->orientation) { + painter->drawLine(r.x(), r.y(), r.x()+r.width()-1, r.y()); + } else if (Qt::RightToLeft==QApplication::layoutDirection()) { + painter->drawLine(r.x()+r.width()-1, r.y(), r.x()+r.width()-1, r.y()+r.height()-1); + } else { + painter->drawLine(r.x(), r.y(), r.x(), r.y()+r.height()-1); + } + if (slider.isValid()) { + painter->setRenderHint(QPainter::Antialiasing, true); + if (Qt::Horizontal==sb->orientation) { + slider.adjust(0, 2, 0, -2); + } else { + slider.adjust(2, 0, -2, 0); + } + QPainterPath path=buildPath(QRectF(slider.x()+0.5, slider.y()+0.5, slider.width()-1, slider.height()-1), + (Qt::Horizontal==sb->orientation ? r.height() : r.width())/4); + QColor col(option->palette.highlight().color()); + if (option->state&State_Active && !(option->state&State_MouseOver)) { + col.setAlphaF(0.75); + } + painter->fillPath(path, col); + if (option->state&State_Active && !(option->state&State_MouseOver)) { + col.setAlphaF(0.25); + } + painter->setPen(col); + painter->drawPath(path); + } + painter->restore(); + return; + } + } + baseStyle()->drawComplexControl(control, option, painter, widget); } diff --git a/gui/gtkproxystyle.h b/gui/gtkproxystyle.h index 3fc0b5221..ffac7cf75 100644 --- a/gui/gtkproxystyle.h +++ b/gui/gtkproxystyle.h @@ -33,9 +33,14 @@ class GtkProxyStyle : public QProxyStyle public: GtkProxyStyle(); QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const; + int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const; + int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const; + QRect subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const; + void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const; private: QComboBox *toolbarCombo; + bool slimScrollbars; }; #endif diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 6121b22cf..93eb2ef67 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -234,7 +234,7 @@ MainWindow::MainWindow(QWidget *parent) Icons::initToolbarIcons(artistLabel->palette().color(QPalette::Foreground)); menuButton->setIcon(Icons::toolbarMenuIcon); if (GtkStyle::isActive()) { - setStyle(new GtkProxyStyle()); + qApp->setStyle(new GtkProxyStyle()); } #ifdef ENABLE_KDE_SUPPORT